mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-12 13:38:21 +00:00
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
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user