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:
Chris Lattner 2005-08-04 22:34:05 +00:00
parent 2ac4fc0320
commit 26d91f1646

View File

@ -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.