diff --git a/src/mapleall/maple_be/include/be/common_utils.h b/src/mapleall/maple_be/include/be/common_utils.h index 2307a9f01631864a38c77aec4a759e94392288a0..522649da5efbc0dea55e048d23f92a05c37b3b59 100644 --- a/src/mapleall/maple_be/include/be/common_utils.h +++ b/src/mapleall/maple_be/include/be/common_utils.h @@ -32,6 +32,7 @@ constexpr uint32 kBaseOffsetAlignment = 3; constexpr uint32 k1FConst = 31; constexpr uint32 k0BitSize = 0; constexpr uint32 k1BitSize = 1; +constexpr uint32 k2BitSize = 2; constexpr uint32 k4BitSize = 4; constexpr uint32 k6BitSize = 6; constexpr uint32 k8BitSize = 8; @@ -125,6 +126,7 @@ constexpr int32 kMaxPimm32 = 16380; constexpr int32 kMaxPimm64 = 32760; constexpr int32 kMaxPimm[k4BitSize] = {kMaxPimm8, kMaxPimm16, kMaxPimm32, kMaxPimm64}; +constexpr int32 kMaxPimm[k2BitSize] = {k256BitSize, k512BitSize}; constexpr int32 kMax12UnsignedImm = 4096; constexpr int32 kMax13UnsignedImm = 8192; 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 c544a2067f5c658aebb64af5e3888d98e6e4d9f1..ad8db970f4a546f7a2f35e70b287f8a9a957eb49 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -453,7 +453,7 @@ class AArch64CGFunc : public CGFunc { RegOperand *GetBaseRegForSplit(uint32 baseRegNum); AArch64MemOperand &SplitOffsetWithAddInstruction(const AArch64MemOperand &memOpnd, uint32 bitLen, uint32 baseRegNum = AArch64reg::kRinvalid, bool isDest = false, - Insn *insn = nullptr); + Insn *insn = nullptr, bool forPair = false); AArch64MemOperand &CreateReplacementMemOperand(uint32 bitLen, RegOperand &baseReg, int32 offset); bool HasStackLoadStore(); diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h index a8fbf05a2555115518ce103c743916fc5310c969..3db5994a9c593a55dcdd8a7eb34cc1138221d455 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h @@ -681,6 +681,17 @@ class AArch64MemOperand : public MemOperand { return (kMaxPimms[alignment]); } + static int32 GetMaxPairPIMM(uint32 dSize) { + ASSERT(dSize >= k32BitSize, "error val:dSize"); + ASSERT(dSize <= k64BitSize, "error val:dSize"); + ASSERT((dSize & (dSize - 1)) == 0, "error val:dSize"); + int32 alignment = GetImmediateOffsetAlignment(dSize); + /* alignment is between kAlignmentOf8Bit and kAlignmentOf64Bit */ + ASSERT(alignment >= kOffsetAlignmentOf32Bit, "error val:alignment"); + ASSERT(alignment <= kOffsetAlignmentOf64Bit, "error val:alignment"); + return (kMaxPairPimms[alignment]); + } + bool IsOffsetMisaligned(uint32 dSize) const { ASSERT(dSize >= k8BitSize, "error val:dSize"); ASSERT(dSize <= k64BitSize, "error val:dSize"); 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 cdc2479c570aae6a62c64688d10cd9b1adcc5bc6..0f64d6e482f6672e4d898a795c0040bfc37c5fe5 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -822,7 +822,8 @@ RegOperand *AArch64CGFunc::GetBaseRegForSplit(uint32 baseRegNum) { } AArch64MemOperand &AArch64CGFunc::SplitOffsetWithAddInstruction(const AArch64MemOperand &memOpnd, uint32 bitLen, - uint32 baseRegNum, bool isDest, Insn *insn) { + uint32 baseRegNum, bool isDest, + Insn *insn, bool forPair) { ASSERT((memOpnd.GetAddrMode() == AArch64MemOperand::kAddrModeBOi), "expect kAddrModeBOi memOpnd"); ASSERT(memOpnd.IsIntactIndexed(), "expect intactIndexed memOpnd"); AArch64OfstOperand *ofstOpnd = memOpnd.GetOffsetImmediate(); @@ -841,9 +842,20 @@ AArch64MemOperand &AArch64CGFunc::SplitOffsetWithAddInstruction(const AArch64Mem * ADD TEMP_REG, X29, ADDEND * LDR/STR TEMP_REG, [ TEMP_REG, #NEW_OFFSET ] */ - int32 maxPimm = memOpnd.GetMaxPIMM(bitLen); + int32 maxPimm = 0; + if (!forPair) { + maxPimm = memOpnd.GetMaxPIMM(bitLen); + } else { + maxPimm = memOpnd.GetMaxPairPIMM(bitLen); + } + ASSERT(maxPimm != 0, "get max pimm failed"); + + bool misAlignment = false; int32 q0 = opndVal / maxPimm; int32 addend = q0 * maxPimm; + if (addend == 0) { + misAlignment = true; + } int32 r0 = opndVal - addend; int32 alignment = memOpnd.GetImmediateOffsetAlignment(bitLen); int32 q1 = static_cast(r0) >> static_cast(alignment); @@ -851,15 +863,44 @@ AArch64MemOperand &AArch64CGFunc::SplitOffsetWithAddInstruction(const AArch64Mem addend = addend + r1; RegOperand *origBaseReg = memOpnd.GetBaseRegister(); ASSERT(origBaseReg != nullptr, "nullptr check"); + + if (misAlignment && addend != 0) { + ImmOperand &immAddend = CreateImmOperand(static_cast(q1) << static_cast(alignment), k64BitSize, true); + if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { + immAddend.SetVary(kUnAdjustVary); + } + + RegOperand *resOpnd = GetBaseRegForSplit(baseRegNum); + if (insn == nullptr) { + SelectAdd(*resOpnd, *origBaseReg, immAddend, PTY_i64); + } else { + SelectAddAfterInsn(*resOpnd, *origBaseReg, immAddend, PTY_i64, isDest, *insn); + } + AArch64MemOperand &newMemOpnd = CreateReplacementMemOperand(bitLen, *resOpnd, r1); + newMemOpnd.SetStackMem(memOpnd.IsStackMem()); + return newMemOpnd; + } if (addend > 0) { int32 t = addend; - constexpr uint32 suffixClear = 0xfffff000; + uint32 suffixClear = 0xfffff000; + if (forPair) { + suffixClear = 0xffffff00; + } addend = (static_cast(addend) & suffixClear); q1 = (static_cast(q1) << static_cast(alignment)) + (t - addend); - if (AArch64MemOperand::IsPIMMOffsetOutOfRange(q1, bitLen)) { - addend = (static_cast(opndVal) & suffixClear); - q1 = opndVal - addend; + if (!forPair) { + if (AArch64MemOperand::IsPIMMOffsetOutOfRange(q1, bitLen)) { + addend = (static_cast(opndVal) & suffixClear); + q1 = opndVal - addend; + } + } else { + if (q1 < 0 || q1 > maxPimm) { + addend = (static_cast(opndVal) & suffixClear); + q1 = opndVal - addend; + } } + + ImmOperand &immAddend = CreateImmOperand(addend, k64BitSize, true); if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { immAddend.SetVary(kUnAdjustVary); @@ -1573,16 +1614,21 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { rhsMemOpnd = FixLargeMemOpnd(*rhsMemOpnd, copySize); /* generate the load */ RegOperand &result = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, std::max(4u, copySize))); - bool doPair = (!rhsIsLo12 && (copySize >= 4) && ((i + 1) < (lhsSize / copySize)) && - !AArch64MemOperand::IsSIMMOffsetOutOfRange(rhsBaseOffset, (copySize == 8), true)); + bool doPair = (!rhsIsLo12 && (copySize >= 4) && ((i + 1) < (lhsSize / copySize))); RegOperand *result1 = nullptr; if (doPair) { regno_t vRegNO1 = NewVReg(kRegTyInt, std::max(4u, copySize)); result1 = &CreateVirtualRegisterOperand(vRegNO1); MOperator mOp = (copySize == 4) ? MOP_wldp : MOP_xldp; + if (!IsOperandImmValid(mOp, rhsMemOpnd, kInsnThirdOpnd)) { + rhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(rhsMemOpnd), result.GetSize(), AArch64reg::kRinvalid, false, nullptr, true); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *result1, *rhsMemOpnd)); } else { MOperator mOp = PickLdInsn(copySize * k8BitSize, PTY_u32); + if (!IsOperandImmValid(mOp, rhsMemOpnd, kInsnSecondOpnd)) { + rhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(rhsMemOpnd), result.GetSize()); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *rhsMemOpnd)); } /* generate the store */ @@ -1591,10 +1637,16 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { static_cast(&lhsAddrOpnd), nullptr, &ofstOpnd, nullptr); if (doPair) { MOperator mOp = (copySize == 4) ? MOP_wstp : MOP_xstp; + if (!IsOperandImmValid(mOp, lhsMemOpnd, kInsnThirdOpnd)) { + lhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(lhsMemOpnd), result.GetSize(), AArch64reg::kRinvalid, false, nullptr, true); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *result1, *lhsMemOpnd)); i++; } else { MOperator mOp = PickStInsn(copySize * k8BitSize, PTY_u32); + if (!IsOperandImmValid(mOp, lhsMemOpnd, kInsnSecondOpnd)) { + lhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(lhsMemOpnd), result.GetSize()); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *lhsMemOpnd)); } } @@ -1685,9 +1737,6 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { AArch64OfstOperand &rhsOfstOpnd = GetOrCreateOfstOpnd(rhsOffset + i * copySize, k32BitSize); Operand *rhsMemOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, operandSize, static_cast(rhsAddrOpnd), nullptr, &rhsOfstOpnd, nullptr); - if (IsImmediateOffsetOutOfRange(*static_cast(rhsMemOpnd), operandSize)) { - rhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(rhsMemOpnd), operandSize); - } RegOperand &result = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, std::max(4u, copySize))); bool doPair = ((copySize >= 4) && ((i + 1) < (lhsSize / copySize))); Insn *insn; @@ -1695,9 +1744,15 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { if (doPair) { result1 = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, std::max(4u, copySize))); MOperator mOp = (copySize == 4) ? MOP_wldp : MOP_xldp; + if (!IsOperandImmValid(mOp, rhsMemOpnd, kInsnThirdOpnd)) { + rhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(rhsMemOpnd), result.GetSize(), AArch64reg::kRinvalid, false, nullptr, true); + } insn = &GetCG()->BuildInstruction(mOp, result, *result1, *rhsMemOpnd); } else { MOperator mOp = PickLdInsn(operandSize, PTY_u32); + if (!IsOperandImmValid(mOp, rhsMemOpnd, kInsnSecondOpnd)) { + rhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(rhsMemOpnd), result.GetSize()); + } insn = &GetCG()->BuildInstruction(mOp, result, *rhsMemOpnd); } insn->MarkAsAccessRefField(isRefField); @@ -1706,15 +1761,18 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { AArch64OfstOperand &lhsOfstOpnd = GetOrCreateOfstOpnd(lhsOffset + i * copySize, k32BitSize); Operand *lhsMemOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, operandSize, static_cast(&lhsAddrOpnd), nullptr, &lhsOfstOpnd, nullptr); - if (IsImmediateOffsetOutOfRange(*static_cast(lhsMemOpnd), operandSize)) { - lhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(lhsMemOpnd), operandSize); - } if (doPair) { MOperator mOp = (copySize == 4) ? MOP_wstp : MOP_xstp; + if (!IsOperandImmValid(mOp, lhsMemOpnd, kInsnThirdOpnd)) { + lhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(lhsMemOpnd), result.GetSize(), AArch64reg::kRinvalid, false, nullptr, true); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *result1, *lhsMemOpnd)); i++; } else { MOperator mOp = PickStInsn(operandSize, PTY_u32); + if (!IsOperandImmValid(mOp, lhsMemOpnd, kInsnSecondOpnd)) { + lhsMemOpnd = &SplitOffsetWithAddInstruction(*static_cast(lhsMemOpnd), result.GetSize()); + } GetCurBB()->AppendInsn(GetCG()->BuildInstruction(mOp, result, *lhsMemOpnd)); } } @@ -5593,7 +5651,11 @@ AArch64RegOperand *AArch64CGFunc::SelectParmListDreadAccessField(const MIRSymbol } else { memOpnd = &GetOrCreateMemOpnd(sym, (kSizeOfPtr * parmNum + offset), memSize); } - GetCurBB()->AppendInsn(cg->BuildInstruction(PickLdInsn(dataSizeBits, primType), *parmOpnd, *memOpnd)); + MOperator selectedMop = PickLdInsn(dataSizeBits, primType); + if (!IsOperandImmValid(selectedMop, memOpnd, kInsnSecondOpnd)) { + memOpnd = &SplitOffsetWithAddInstruction(*static_cast(memOpnd), dataSizeBits); + } + GetCurBB()->AppendInsn(cg->BuildInstruction(selectedMop, *parmOpnd, *memOpnd)); return parmOpnd; } @@ -5620,7 +5682,11 @@ void AArch64CGFunc::CreateCallStructParamPassByReg(AArch64reg reg, MemOperand &m ASSERT(0, "CreateCallStructParamPassByReg: Unknown state"); } - GetCurBB()->AppendInsn(cg->BuildInstruction(PickLdInsn(dataSizeBits, pType), *parmOpnd, memOpnd)); + MOperator selectedMop = PickLdInsn(dataSizeBits, pType); + if (!IsOperandImmValid(selectedMop, memOpnd, kInsnSecondOpnd)) { + memOpnd = &SplitOffsetWithAddInstruction(*static_cast(memOpnd), dataSizeBits); + } + GetCurBB()->AppendInsn(cg->BuildInstruction(PickLdInsn(selectedMop, *parmOpnd, memOpnd)); srcOpnds.PushOpnd(*parmOpnd); } diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp index 3cd16e26c986ee1b5ed4aa4286b03db0bceb3816..561106aa209bfa3b9f856b2d210e3b49484a07be 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp @@ -26,7 +26,6 @@ const std::set kFrameWhiteListFunc { bool IsFuncNeedFrame(const std::string &funcName) { return kFrameWhiteListFunc.find(funcName) != kFrameWhiteListFunc.end(); } -constexpr uint32 k2BitSize = 2; constexpr int32 kSoeChckOffset = 8192; enum RegsPushPop : uint8 {