mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-16 11:30:51 +00:00
Modify how immediates are removed from base expressions to deal with the fact
that the symbolic evaluator is not always able to use subtraction to remove expressions. This makes the code faster, and fixes the last crash on 178.galgel. Finally, add a statistic to see how many phi nodes are inserted. On 178.galgel, we get the follow stats: 2562 loop-reduce - Number of PHIs inserted 3927 loop-reduce - Number of GEPs strength reduced git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22662 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2ac4fc0320
commit
26d91f1646
@ -36,6 +36,7 @@ using namespace llvm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Statistic<> NumReduced ("loop-reduce", "Number of GEPs strength reduced");
|
Statistic<> NumReduced ("loop-reduce", "Number of GEPs strength reduced");
|
||||||
|
Statistic<> NumInserted("loop-reduce", "Number of PHIs inserted");
|
||||||
|
|
||||||
/// IVStrideUse - Keep track of one use of a strided induction variable, where
|
/// IVStrideUse - Keep track of one use of a strided induction variable, where
|
||||||
/// the stride is stored externally. The Offset member keeps track of the
|
/// the stride is stored externally. The Offset member keeps track of the
|
||||||
@ -433,38 +434,54 @@ static bool isTargetConstant(const SCEVHandle &V) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GetImmediateValues - Look at Val, and pull out any additions of constants
|
/// MoveImmediateValues - Look at Val, and pull out any additions of constants
|
||||||
/// that can fit into the immediate field of instructions in the target.
|
/// that can fit into the immediate field of instructions in the target.
|
||||||
static SCEVHandle GetImmediateValues(SCEVHandle Val, bool isAddress, Loop *L) {
|
/// Accumulate these immediate values into the Imm value.
|
||||||
if (isAddress && isTargetConstant(Val))
|
static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
|
||||||
return Val;
|
bool isAddress, Loop *L) {
|
||||||
|
|
||||||
if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) {
|
if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) {
|
||||||
unsigned i = 0;
|
std::vector<SCEVHandle> NewOps;
|
||||||
SCEVHandle Imm = SCEVUnknown::getIntegerSCEV(0, Val->getType());
|
NewOps.reserve(SAE->getNumOperands());
|
||||||
|
|
||||||
for (; i != SAE->getNumOperands(); ++i)
|
for (unsigned i = 0; i != SAE->getNumOperands(); ++i)
|
||||||
if (isAddress && isTargetConstant(SAE->getOperand(i))) {
|
if (isAddress && isTargetConstant(SAE->getOperand(i))) {
|
||||||
Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
|
Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
|
||||||
} else if (!SAE->getOperand(i)->isLoopInvariant(L)) {
|
} else if (!SAE->getOperand(i)->isLoopInvariant(L)) {
|
||||||
// If this is a loop-variant expression, it must stay in the immediate
|
// If this is a loop-variant expression, it must stay in the immediate
|
||||||
// field of the expression.
|
// field of the expression.
|
||||||
Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
|
Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
|
||||||
|
} else {
|
||||||
|
NewOps.push_back(SAE->getOperand(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Imm;
|
if (NewOps.empty())
|
||||||
|
Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
|
||||||
|
else
|
||||||
|
Val = SCEVAddExpr::get(NewOps);
|
||||||
|
return;
|
||||||
} else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) {
|
} else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) {
|
||||||
// Try to pull immediates out of the start value of nested addrec's.
|
// Try to pull immediates out of the start value of nested addrec's.
|
||||||
return GetImmediateValues(SARE->getStart(), isAddress, L);
|
SCEVHandle Start = SARE->getStart();
|
||||||
|
MoveImmediateValues(Start, Imm, isAddress, L);
|
||||||
|
|
||||||
|
if (Start != SARE->getStart()) {
|
||||||
|
std::vector<SCEVHandle> Ops(SARE->op_begin(), SARE->op_end());
|
||||||
|
Ops[0] = Start;
|
||||||
|
Val = SCEVAddRecExpr::get(Ops, SARE->getLoop());
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Val->isLoopInvariant(L)) {
|
// Loop-variant expressions must stay in the immediate field of the
|
||||||
// If this is a loop-variant expression, it must stay in the immediate
|
// expression.
|
||||||
// field of the expression.
|
if ((isAddress && isTargetConstant(Val)) ||
|
||||||
return Val;
|
!Val->isLoopInvariant(L)) {
|
||||||
|
Imm = SCEVAddExpr::get(Imm, Val);
|
||||||
|
Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCEVUnknown::getIntegerSCEV(0, Val->getType());
|
// Otherwise, no immediates to move.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// StrengthReduceStridedIVUsers - Strength reduce all of the users of a single
|
/// StrengthReduceStridedIVUsers - Strength reduce all of the users of a single
|
||||||
@ -502,14 +519,11 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(Value *Stride,
|
|||||||
if (SI->getOperand(1) == UsersToProcess[i].second.OperandValToReplace)
|
if (SI->getOperand(1) == UsersToProcess[i].second.OperandValToReplace)
|
||||||
isAddress = true;
|
isAddress = true;
|
||||||
|
|
||||||
UsersToProcess[i].second.Imm =
|
MoveImmediateValues(UsersToProcess[i].first, UsersToProcess[i].second.Imm,
|
||||||
GetImmediateValues(UsersToProcess[i].first, isAddress, L);
|
isAddress, L);
|
||||||
|
|
||||||
UsersToProcess[i].first = SCEV::getMinusSCEV(UsersToProcess[i].first,
|
|
||||||
UsersToProcess[i].second.Imm);
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "BASE: " << *UsersToProcess[i].first);
|
assert(UsersToProcess[i].first->isLoopInvariant(L) &&
|
||||||
DEBUG(UsersToProcess[i].second.dump());
|
"Base value is not loop invariant!");
|
||||||
}
|
}
|
||||||
|
|
||||||
SCEVExpander Rewriter(*SE, *LI);
|
SCEVExpander Rewriter(*SE, *LI);
|
||||||
@ -545,6 +559,7 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(Value *Stride,
|
|||||||
// Create a new Phi for this base, and stick it in the loop header.
|
// Create a new Phi for this base, and stick it in the loop header.
|
||||||
const Type *ReplacedTy = Base->getType();
|
const Type *ReplacedTy = Base->getType();
|
||||||
PHINode *NewPHI = new PHINode(ReplacedTy, "iv.", PhiInsertBefore);
|
PHINode *NewPHI = new PHINode(ReplacedTy, "iv.", PhiInsertBefore);
|
||||||
|
++NumInserted;
|
||||||
|
|
||||||
// Emit the initial base value into the loop preheader, and add it to the
|
// Emit the initial base value into the loop preheader, and add it to the
|
||||||
// Phi node.
|
// Phi node.
|
||||||
|
Loading…
Reference in New Issue
Block a user