diff options
author | Momchil Velikov <momchil.velikov@arm.com> | 2023-04-20 14:51:47 +0100 |
---|---|---|
committer | Momchil Velikov <momchil.velikov@arm.com> | 2023-04-20 15:43:11 +0100 |
commit | 0827e2fa3fd15b49fd2d0fc676753f11abb60cab (patch) | |
tree | 58174376622268c8ea0e9b9872b078e284bfc329 /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | e0d884de360b5c3fe79c6a53f8f88b57f0e42275 (diff) | |
download | llvm-0827e2fa3fd15b49fd2d0fc676753f11abb60cab.zip llvm-0827e2fa3fd15b49fd2d0fc676753f11abb60cab.tar.gz llvm-0827e2fa3fd15b49fd2d0fc676753f11abb60cab.tar.bz2 |
[AArch64] Fix incorrect `isLegalAddressingMode`
`AArch64TargetLowering::isLegalAddressingMode` has a number of
defects, including accepting an addressing mode which consists of only
an immediate operand, or not checking the offset range for an
addressing mode in the form `1*ScaledReg + Offs`.
This patch fixes the above issues.
Reviewed By: dmgreen
Differential Revision: https://reviews.llvm.org/D143895
Change-Id: I756fa21941844ded44f082ac7eea4391219f9851
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 55ba545..95cad24 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -4629,7 +4629,8 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode, return false; } case Instruction::Add: { - // Check to see if we can merge in the RHS then the LHS. If so, we win. + // Check to see if we can merge in one operand, then the other. If so, we + // win. ExtAddrMode BackupAddrMode = AddrMode; unsigned OldSize = AddrModeInsts.size(); // Start a transaction at this point. @@ -4639,9 +4640,15 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode, TypePromotionTransaction::ConstRestorationPt LastKnownGood = TPT.getRestorationPoint(); + // Try to match an integer constant second to increase its chance of ending + // up in `BaseOffs`, resp. decrease its chance of ending up in `BaseReg`. + int First = 0, Second = 1; + if (isa<ConstantInt>(AddrInst->getOperand(First)) + && !isa<ConstantInt>(AddrInst->getOperand(Second))) + std::swap(First, Second); AddrMode.InBounds = false; - if (matchAddr(AddrInst->getOperand(1), Depth + 1) && - matchAddr(AddrInst->getOperand(0), Depth + 1)) + if (matchAddr(AddrInst->getOperand(First), Depth + 1) && + matchAddr(AddrInst->getOperand(Second), Depth + 1)) return true; // Restore the old addr mode info. @@ -4649,9 +4656,10 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode, AddrModeInsts.resize(OldSize); TPT.rollback(LastKnownGood); - // Otherwise this was over-aggressive. Try merging in the LHS then the RHS. - if (matchAddr(AddrInst->getOperand(0), Depth + 1) && - matchAddr(AddrInst->getOperand(1), Depth + 1)) + // Otherwise this was over-aggressive. Try merging operands in the opposite + // order. + if (matchAddr(AddrInst->getOperand(Second), Depth + 1) && + matchAddr(AddrInst->getOperand(First), Depth + 1)) return true; // Otherwise we definitely can't merge the ADD in. @@ -4720,36 +4728,35 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode, // just add it to the disp field and check validity. if (VariableOperand == -1) { AddrMode.BaseOffs += ConstantOffset; - if (ConstantOffset == 0 || - TLI.isLegalAddressingMode(DL, AddrMode, AccessTy, AddrSpace)) { - // Check to see if we can fold the base pointer in too. - if (matchAddr(AddrInst->getOperand(0), Depth + 1)) { + if (matchAddr(AddrInst->getOperand(0), Depth + 1)) { if (!cast<GEPOperator>(AddrInst)->isInBounds()) AddrMode.InBounds = false; return true; - } - } else if (EnableGEPOffsetSplit && isa<GetElementPtrInst>(AddrInst) && - TLI.shouldConsiderGEPOffsetSplit() && Depth == 0 && - ConstantOffset > 0) { - // Record GEPs with non-zero offsets as candidates for splitting in the - // event that the offset cannot fit into the r+i addressing mode. - // Simple and common case that only one GEP is used in calculating the - // address for the memory access. - Value *Base = AddrInst->getOperand(0); - auto *BaseI = dyn_cast<Instruction>(Base); - auto *GEP = cast<GetElementPtrInst>(AddrInst); - if (isa<Argument>(Base) || isa<GlobalValue>(Base) || - (BaseI && !isa<CastInst>(BaseI) && - !isa<GetElementPtrInst>(BaseI))) { - // Make sure the parent block allows inserting non-PHI instructions - // before the terminator. - BasicBlock *Parent = - BaseI ? BaseI->getParent() : &GEP->getFunction()->getEntryBlock(); - if (!Parent->getTerminator()->isEHPad()) - LargeOffsetGEP = std::make_pair(GEP, ConstantOffset); - } } AddrMode.BaseOffs -= ConstantOffset; + + if (EnableGEPOffsetSplit && isa<GetElementPtrInst>(AddrInst) && + TLI.shouldConsiderGEPOffsetSplit() && Depth == 0 && + ConstantOffset > 0) { + // Record GEPs with non-zero offsets as candidates for splitting in + // the event that the offset cannot fit into the r+i addressing mode. + // Simple and common case that only one GEP is used in calculating the + // address for the memory access. + Value *Base = AddrInst->getOperand(0); + auto *BaseI = dyn_cast<Instruction>(Base); + auto *GEP = cast<GetElementPtrInst>(AddrInst); + if (isa<Argument>(Base) || isa<GlobalValue>(Base) || + (BaseI && !isa<CastInst>(BaseI) && + !isa<GetElementPtrInst>(BaseI))) { + // Make sure the parent block allows inserting non-PHI instructions + // before the terminator. + BasicBlock *Parent = BaseI ? BaseI->getParent() + : &GEP->getFunction()->getEntryBlock(); + if (!Parent->getTerminator()->isEHPad()) + LargeOffsetGEP = std::make_pair(GEP, ConstantOffset); + } + } + return false; } @@ -6034,6 +6041,7 @@ bool CodeGenPrepare::splitLargeGEPOffsets() { int64_t Offset = LargeOffsetGEP->second; if (Offset != BaseOffset) { TargetLowering::AddrMode AddrMode; + AddrMode.HasBaseReg = true; AddrMode.BaseOffs = Offset - BaseOffset; // The result type of the GEP might not be the type of the memory // access. |