diff options
author | Dan Gohman <gohman@apple.com> | 2009-05-19 02:15:55 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2009-05-19 02:15:55 +0000 |
commit | d0c0123eb99be0b2a3653f89f7410271683acf06 (patch) | |
tree | 77d5bd8b1b5961b4ed2fd11e271e32fe9ce2fd99 /lib/Transforms/Utils | |
parent | 1750579b285d88fd0536187f270fa6a18d405fd1 (diff) | |
download | external_llvm-d0c0123eb99be0b2a3653f89f7410271683acf06.zip external_llvm-d0c0123eb99be0b2a3653f89f7410271683acf06.tar.gz external_llvm-d0c0123eb99be0b2a3653f89f7410271683acf06.tar.bz2 |
Teach SCEVExpander to expand arithmetic involving pointers into GEP
instructions. It attempts to create high-level multi-operand GEPs,
though in cases where this isn't possible it falls back to casting
the pointer to i8* and emitting a GEP with that. Using GEP instructions
instead of ptrtoint+arithmetic+inttoptr helps pointer analyses that
don't use ScalarEvolution, such as BasicAliasAnalysis.
Also, make the AddrModeMatcher more aggressive in handling GEPs.
Previously it assumed that operand 0 of a GEP would require a register
in almost all cases. It now does extra checking and can do more
matching if operand 0 of the GEP is foldable. This fixes a problem
that was exposed by SCEVExpander using GEPs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72093 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils')
-rw-r--r-- | lib/Transforms/Utils/AddrModeMatcher.cpp | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/lib/Transforms/Utils/AddrModeMatcher.cpp b/lib/Transforms/Utils/AddrModeMatcher.cpp index b820dd3..71049fa 100644 --- a/lib/Transforms/Utils/AddrModeMatcher.cpp +++ b/lib/Transforms/Utils/AddrModeMatcher.cpp @@ -255,43 +255,44 @@ bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode, // Save the valid addressing mode in case we can't match. ExtAddrMode BackupAddrMode = AddrMode; - - // Check that this has no base reg yet. If so, we won't have a place to - // put the base of the GEP (assuming it is not a null ptr). - bool SetBaseReg = true; - if (isa<ConstantPointerNull>(AddrInst->getOperand(0))) - SetBaseReg = false; // null pointer base doesn't need representation. - else if (AddrMode.HasBaseReg) - return false; // Base register already specified, can't match GEP. - else { - // Otherwise, we'll use the GEP base as the BaseReg. + unsigned OldSize = AddrModeInsts.size(); + + // See if the scale and offset amount is valid for this target. + AddrMode.BaseOffs += ConstantOffset; + + // Match the base operand of the GEP. + if (!MatchAddr(AddrInst->getOperand(0), Depth+1)) { + // If it couldn't be matched, just stuff the value in a register. + if (AddrMode.HasBaseReg) { + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + return false; + } AddrMode.HasBaseReg = true; AddrMode.BaseReg = AddrInst->getOperand(0); } - - // See if the scale and offset amount is valid for this target. - AddrMode.BaseOffs += ConstantOffset; - + + // Match the remaining variable portion of the GEP. if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), VariableScale, Depth)) { + // If it couldn't be matched, try stuffing the base into a register + // instead of matching it, and retrying the match of the scale. AddrMode = BackupAddrMode; - return false; + AddrModeInsts.resize(OldSize); + if (AddrMode.HasBaseReg) + return false; + AddrMode.HasBaseReg = true; + AddrMode.BaseReg = AddrInst->getOperand(0); + AddrMode.BaseOffs += ConstantOffset; + if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), + VariableScale, Depth)) { + // If even that didn't work, bail. + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + return false; + } } - - // If we have a null as the base of the GEP, folding in the constant offset - // plus variable scale is all we can do. - if (!SetBaseReg) return true; - - // If this match succeeded, we know that we can form an address with the - // GepBase as the basereg. Match the base pointer of the GEP more - // aggressively by zeroing out BaseReg and rematching. If the base is - // (for example) another GEP, this allows merging in that other GEP into - // the addressing mode we're forming. - AddrMode.HasBaseReg = false; - AddrMode.BaseReg = 0; - bool Success = MatchAddr(AddrInst->getOperand(0), Depth+1); - assert(Success && "MatchAddr should be able to fill in BaseReg!"); - Success=Success; + return true; } } |