diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h index 1f4410d0f2feb172b7e1ebc321a3b0b651cfb551..17c6d21c1d57f3d14df7f05bd34756a31add847c 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -435,6 +435,7 @@ class AArch64CGFunc : public CGFunc { MOperator PickStInsn(uint32 bitSize, PrimType primType, AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone); MOperator PickLdInsn(uint32 bitSize, PrimType primType, AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone); + MOperator PickExtInsn(PrimType dtype, PrimType stype); bool CheckIfSplitOffsetWithAdd(const AArch64MemOperand &memOpnd, uint32 bitLen); AArch64MemOperand &SplitOffsetWithAddInstruction(const AArch64MemOperand &memOpnd, uint32 bitLen, @@ -566,6 +567,10 @@ class AArch64CGFunc : public CGFunc { return (o.IsRegister() ? static_cast(o) : SelectCopy(o, oty, oty)); } + RegOperand &LoadIntoRegister(Operand &o, PrimType dty, PrimType sty) { + return (o.IsRegister() ? static_cast(o) : SelectCopy(o, sty, dty)); + } + void CreateCallStructParamPassByStack(int32 symSize, MIRSymbol *sym, RegOperand *addrOpnd, int32 baseOffset); void CreateCallStructParamPassByReg(AArch64reg reg, MemOperand &memOpnd, AArch64ListOperand &srcOpnds, fpParamState state); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index ae4ddad5a48eb3f1e50fdda787fc0d28b53602d2..82f2ce38dca97459cfd4e097cc278ce41e560cf8 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -74,6 +74,26 @@ MOperator stFs[kFloatByteSizeDimension] = { MOP_sstr, MOP_dstr }; MOperator ldFsAcq[kFloatByteSizeDimension] = { MOP_undef, MOP_undef }; MOperator stFsRel[kFloatByteSizeDimension] = { MOP_undef, MOP_undef }; +/* extended to unsigned ints */ +MOperator uextIs[kIntByteSizeDimension][kIntByteSizeDimension] = { + /* u8 u16 u32 u64 */ + { MOP_undef, MOP_xuxtb32, MOP_xuxtb32, MOP_xuxtb32}, /* u8/i8 */ + { MOP_undef, MOP_undef, MOP_xuxth32, MOP_xuxth32}, /* u16/i16 */ + { MOP_undef, MOP_undef, MOP_xuxtw64, MOP_xuxtw64}, /* u32/i32 */ + { MOP_undef, MOP_undef, MOP_undef, MOP_undef} /* u64/u64 */ +}; + +/* extended to signed ints */ +MOperator extIs[kIntByteSizeDimension][kIntByteSizeDimension] = { + /* i8 i16 i32 i64 */ + { MOP_undef, MOP_xsxtb32, MOP_xsxtb32, MOP_xsxtb64}, /* u8/i8 */ + { MOP_undef, MOP_undef, MOP_xsxth32, MOP_xsxth64}, /* u16/i16 */ + { MOP_undef, MOP_undef, MOP_undef, MOP_xsxtw64}, /* u32/i32 */ + { MOP_undef, MOP_undef, MOP_undef, MOP_undef} /* u64/u64 */ +}; + +/* extended to signed ints */ + MOperator PickLdStInsn(bool isLoad, uint32 bitSize, PrimType primType, AArch64isa::MemoryOrdering memOrd) { ASSERT(__builtin_popcount(static_cast(memOrd)) <= 1, "must be kMoNone or kMoAcquire"); ASSERT(primType != PTY_ptr, "should have been lowered"); @@ -126,6 +146,24 @@ MOperator AArch64CGFunc::PickStInsn(uint32 bitSize, PrimType primType, AArch64is return PickLdStInsn(false, bitSize, primType, memOrd); } +MOperator AArch64CGFunc::PickExtInsn(PrimType dtype, PrimType stype) { + int32 sBitSize = GetPrimTypeBitSize(stype); + int32 dBitSize = GetPrimTypeBitSize(dtype); + /* __builtin_ffs(x) returns: 0 -> 0, 1 -> 1, 2 -> 2, 4 -> 3, 8 -> 4 */ + if (IsPrimitiveInteger(stype) && IsPrimitiveInteger(dtype)) { + MOperator(*table)[kIntByteSizeDimension]; + table = IsUnsignedInteger(dtype) ? uextIs : extIs; + /* __builtin_ffs(x) returns: 8 -> 4, 16 -> 5, 32 -> 6, 64 -> 7 */ + uint32 row = static_cast(__builtin_ffs(static_cast(sBitSize))) - 4; + ASSERT(row <= 3, "wrong bitSize"); + uint32 col = static_cast(__builtin_ffs(static_cast(dBitSize))) - 4; + ASSERT(col <= 3, "wrong bitSize"); + return table[row][col]; + } + CHECK_FATAL(0, "extend not primitive integer"); + return MOP_undef; +} + MOperator AArch64CGFunc::PickMovInsn(PrimType primType) { switch (primType) { case PTY_u8: @@ -429,11 +467,21 @@ void AArch64CGFunc::SelectCopyMemOpnd(Operand &dest, PrimType dtype, uint32 dsiz } Insn *insn = nullptr; uint32 ssize = src.GetSize(); + PrimType regTy = PTY_void; + RegOperand *loadReg; + MOperator mop = MOP_undef; if (IsPrimitiveFloat(stype)) { CHECK_FATAL(dsize == ssize, "dsize %u expect equals ssize %u", dtype, ssize); insn = &GetCG()->BuildInstruction(PickLdInsn(ssize, stype), dest, src); } else { - insn = &GetCG()->BuildInstruction(PickLdInsn(ssize, stype), dest, src); + mop = PickExtInsn(dtype, stype); + if (ssize == (GetPrimTypeSize(dtype) * kBitsPerByte) || mop == MOP_undef) { + insn = &GetCG()->BuildInstruction(PickLdInsn(ssize, stype), dest, src); + } else { + regTy = dsize == k64BitSize ? dtype : PTY_i32; + loadReg = &CreateRegisterOperandOfType(regTy); + insn = &GetCG()->BuildInstruction(PickLdInsn(ssize, stype), *loadReg, src); + } } if (GetCG()->GenerateVerboseCG()) { @@ -453,6 +501,10 @@ void AArch64CGFunc::SelectCopyMemOpnd(Operand &dest, PrimType dtype, uint32 dsiz } GetCurBB()->AppendInsn(*insn); + + if (regTy != PTY_void && mop != MOP_undef) { + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mop, dest, *loadReg)); + } } bool AArch64CGFunc::IsImmediateValueInRange(MOperator mOp, int64 immVal, bool is64Bits, @@ -1533,6 +1585,10 @@ Operand *AArch64CGFunc::SelectDread(const BaseNode &parent, DreadNode &expr) { IsImmediateOffsetOutOfRange(*static_cast(memOpnd), dataSize)) { return &SplitOffsetWithAddInstruction(*static_cast(memOpnd), dataSize); } + if (symType != expr.GetPrimType()) { + RegOperand *opnd = &LoadIntoRegister(*memOpnd, expr.GetPrimType(), symType); + return opnd; + } return memOpnd; } diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_operand.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_operand.cpp index 1d2c84df475f3093525527391cba27d632078c6c..2681590c7f223f3bf3c36de74f7188edceb9f3a2 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_operand.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_operand.cpp @@ -175,11 +175,7 @@ bool StImmOperand::Less(const Operand &right) const{ void StImmOperand::Emit(Emitter &emitter, const OpndProp *opndProp) const { CHECK_FATAL(opndProp != nullptr, "opndProp is nullptr in StImmOperand::Emit"); if (static_cast(opndProp)->IsLiteralLow12()) { - emitter.Emit("#:lo12:" + GetName()); - if (offset != 0) { - emitter.Emit("+" + std::to_string(offset)); - } - return; + emitter.Emit("#:lo12:"); } if (CGOptions::IsPIC() && (symbol->GetStorageClass() == kScGlobal || symbol->GetStorageClass() == kScExtern)) { emitter.Emit(":got:" + GetName());