mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
Merging 182989: Fix ScalarEvolution::ComputeExitLimitFromCond for 'or' conditions.
Fixes PR16130 - clang produces incorrect code with loop/expression at -O2. This is a 2+ year old bug that's now holding up the release. It's a case where we knowingly made aggressive assumptions about undefined behavior. These assumptions are wrong when SCEV is computing a subexpression that does not directly control the branch. With this fix, we avoid making assumptions in those cases but still optimize the common case. SCEV's trip count computation for exits controlled by 'or' expressions is now analagous to the trip count computation for loops with multiple exits. I had already fixed the multiple exit case to be conservative. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182989 91177308-0d34-0410-b5e6-96231b3b80d8 git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_33@183013 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -453,7 +453,8 @@ namespace llvm {
|
|||||||
ExitLimit ComputeExitLimitFromCond(const Loop *L,
|
ExitLimit ComputeExitLimitFromCond(const Loop *L,
|
||||||
Value *ExitCond,
|
Value *ExitCond,
|
||||||
BasicBlock *TBB,
|
BasicBlock *TBB,
|
||||||
BasicBlock *FBB);
|
BasicBlock *FBB,
|
||||||
|
bool IsSubExpr);
|
||||||
|
|
||||||
/// ComputeExitLimitFromICmp - Compute the number of times the backedge of
|
/// ComputeExitLimitFromICmp - Compute the number of times the backedge of
|
||||||
/// the specified loop will execute if its exit condition were a conditional
|
/// the specified loop will execute if its exit condition were a conditional
|
||||||
@@ -461,7 +462,8 @@ namespace llvm {
|
|||||||
ExitLimit ComputeExitLimitFromICmp(const Loop *L,
|
ExitLimit ComputeExitLimitFromICmp(const Loop *L,
|
||||||
ICmpInst *ExitCond,
|
ICmpInst *ExitCond,
|
||||||
BasicBlock *TBB,
|
BasicBlock *TBB,
|
||||||
BasicBlock *FBB);
|
BasicBlock *FBB,
|
||||||
|
bool IsSubExpr);
|
||||||
|
|
||||||
/// ComputeLoadConstantCompareExitLimit - Given an exit condition
|
/// ComputeLoadConstantCompareExitLimit - Given an exit condition
|
||||||
/// of 'icmp op load X, cst', try to see if we can compute the
|
/// of 'icmp op load X, cst', try to see if we can compute the
|
||||||
@@ -483,7 +485,7 @@ namespace llvm {
|
|||||||
/// HowFarToZero - Return the number of times an exit condition comparing
|
/// HowFarToZero - Return the number of times an exit condition comparing
|
||||||
/// the specified value to zero will execute. If not computable, return
|
/// the specified value to zero will execute. If not computable, return
|
||||||
/// CouldNotCompute.
|
/// CouldNotCompute.
|
||||||
ExitLimit HowFarToZero(const SCEV *V, const Loop *L);
|
ExitLimit HowFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr);
|
||||||
|
|
||||||
/// HowFarToNonZero - Return the number of times an exit condition checking
|
/// HowFarToNonZero - Return the number of times an exit condition checking
|
||||||
/// the specified value for nonzero will execute. If not computable, return
|
/// the specified value for nonzero will execute. If not computable, return
|
||||||
@@ -495,7 +497,7 @@ namespace llvm {
|
|||||||
/// computable, return CouldNotCompute. isSigned specifies whether the
|
/// computable, return CouldNotCompute. isSigned specifies whether the
|
||||||
/// less-than is signed.
|
/// less-than is signed.
|
||||||
ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
||||||
const Loop *L, bool isSigned);
|
const Loop *L, bool isSigned, bool IsSubExpr);
|
||||||
|
|
||||||
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
|
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
|
||||||
/// (which may not be an immediate predecessor) which has exactly one
|
/// (which may not be an immediate predecessor) which has exactly one
|
||||||
|
@@ -4382,26 +4382,36 @@ ScalarEvolution::ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock) {
|
|||||||
// Proceed to the next level to examine the exit condition expression.
|
// Proceed to the next level to examine the exit condition expression.
|
||||||
return ComputeExitLimitFromCond(L, ExitBr->getCondition(),
|
return ComputeExitLimitFromCond(L, ExitBr->getCondition(),
|
||||||
ExitBr->getSuccessor(0),
|
ExitBr->getSuccessor(0),
|
||||||
ExitBr->getSuccessor(1));
|
ExitBr->getSuccessor(1),
|
||||||
|
/*IsSubExpr=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ComputeExitLimitFromCond - Compute the number of times the
|
/// ComputeExitLimitFromCond - Compute the number of times the
|
||||||
/// backedge of the specified loop will execute if its exit condition
|
/// backedge of the specified loop will execute if its exit condition
|
||||||
/// were a conditional branch of ExitCond, TBB, and FBB.
|
/// were a conditional branch of ExitCond, TBB, and FBB.
|
||||||
|
///
|
||||||
|
/// @param IsSubExpr is true if ExitCond does not directly control the exit
|
||||||
|
/// branch. In this case, we cannot assume that the loop only exits when the
|
||||||
|
/// condition is true and cannot infer that failing to meet the condition prior
|
||||||
|
/// to integer wraparound results in undefined behavior.
|
||||||
ScalarEvolution::ExitLimit
|
ScalarEvolution::ExitLimit
|
||||||
ScalarEvolution::ComputeExitLimitFromCond(const Loop *L,
|
ScalarEvolution::ComputeExitLimitFromCond(const Loop *L,
|
||||||
Value *ExitCond,
|
Value *ExitCond,
|
||||||
BasicBlock *TBB,
|
BasicBlock *TBB,
|
||||||
BasicBlock *FBB) {
|
BasicBlock *FBB,
|
||||||
|
bool IsSubExpr) {
|
||||||
// Check if the controlling expression for this loop is an And or Or.
|
// Check if the controlling expression for this loop is an And or Or.
|
||||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(ExitCond)) {
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(ExitCond)) {
|
||||||
if (BO->getOpcode() == Instruction::And) {
|
if (BO->getOpcode() == Instruction::And) {
|
||||||
// Recurse on the operands of the and.
|
// Recurse on the operands of the and.
|
||||||
ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB);
|
bool EitherMayExit = L->contains(TBB);
|
||||||
ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB);
|
ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB,
|
||||||
|
IsSubExpr || EitherMayExit);
|
||||||
|
ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB,
|
||||||
|
IsSubExpr || EitherMayExit);
|
||||||
const SCEV *BECount = getCouldNotCompute();
|
const SCEV *BECount = getCouldNotCompute();
|
||||||
const SCEV *MaxBECount = getCouldNotCompute();
|
const SCEV *MaxBECount = getCouldNotCompute();
|
||||||
if (L->contains(TBB)) {
|
if (EitherMayExit) {
|
||||||
// Both conditions must be true for the loop to continue executing.
|
// Both conditions must be true for the loop to continue executing.
|
||||||
// Choose the less conservative count.
|
// Choose the less conservative count.
|
||||||
if (EL0.Exact == getCouldNotCompute() ||
|
if (EL0.Exact == getCouldNotCompute() ||
|
||||||
@@ -4429,11 +4439,14 @@ ScalarEvolution::ComputeExitLimitFromCond(const Loop *L,
|
|||||||
}
|
}
|
||||||
if (BO->getOpcode() == Instruction::Or) {
|
if (BO->getOpcode() == Instruction::Or) {
|
||||||
// Recurse on the operands of the or.
|
// Recurse on the operands of the or.
|
||||||
ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB);
|
bool EitherMayExit = L->contains(FBB);
|
||||||
ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB);
|
ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB,
|
||||||
|
IsSubExpr || EitherMayExit);
|
||||||
|
ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB,
|
||||||
|
IsSubExpr || EitherMayExit);
|
||||||
const SCEV *BECount = getCouldNotCompute();
|
const SCEV *BECount = getCouldNotCompute();
|
||||||
const SCEV *MaxBECount = getCouldNotCompute();
|
const SCEV *MaxBECount = getCouldNotCompute();
|
||||||
if (L->contains(FBB)) {
|
if (EitherMayExit) {
|
||||||
// Both conditions must be false for the loop to continue executing.
|
// Both conditions must be false for the loop to continue executing.
|
||||||
// Choose the less conservative count.
|
// Choose the less conservative count.
|
||||||
if (EL0.Exact == getCouldNotCompute() ||
|
if (EL0.Exact == getCouldNotCompute() ||
|
||||||
@@ -4464,7 +4477,7 @@ ScalarEvolution::ComputeExitLimitFromCond(const Loop *L,
|
|||||||
// With an icmp, it may be feasible to compute an exact backedge-taken count.
|
// With an icmp, it may be feasible to compute an exact backedge-taken count.
|
||||||
// Proceed to the next level to examine the icmp.
|
// Proceed to the next level to examine the icmp.
|
||||||
if (ICmpInst *ExitCondICmp = dyn_cast<ICmpInst>(ExitCond))
|
if (ICmpInst *ExitCondICmp = dyn_cast<ICmpInst>(ExitCond))
|
||||||
return ComputeExitLimitFromICmp(L, ExitCondICmp, TBB, FBB);
|
return ComputeExitLimitFromICmp(L, ExitCondICmp, TBB, FBB, IsSubExpr);
|
||||||
|
|
||||||
// Check for a constant condition. These are normally stripped out by
|
// Check for a constant condition. These are normally stripped out by
|
||||||
// SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to
|
// SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to
|
||||||
@@ -4490,7 +4503,8 @@ ScalarEvolution::ExitLimit
|
|||||||
ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L,
|
ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L,
|
||||||
ICmpInst *ExitCond,
|
ICmpInst *ExitCond,
|
||||||
BasicBlock *TBB,
|
BasicBlock *TBB,
|
||||||
BasicBlock *FBB) {
|
BasicBlock *FBB,
|
||||||
|
bool IsSubExpr) {
|
||||||
|
|
||||||
// If the condition was exit on true, convert the condition to exit on false
|
// If the condition was exit on true, convert the condition to exit on false
|
||||||
ICmpInst::Predicate Cond;
|
ICmpInst::Predicate Cond;
|
||||||
@@ -4542,7 +4556,7 @@ ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L,
|
|||||||
switch (Cond) {
|
switch (Cond) {
|
||||||
case ICmpInst::ICMP_NE: { // while (X != Y)
|
case ICmpInst::ICMP_NE: { // while (X != Y)
|
||||||
// Convert to: while (X-Y != 0)
|
// Convert to: while (X-Y != 0)
|
||||||
ExitLimit EL = HowFarToZero(getMinusSCEV(LHS, RHS), L);
|
ExitLimit EL = HowFarToZero(getMinusSCEV(LHS, RHS), L, IsSubExpr);
|
||||||
if (EL.hasAnyInfo()) return EL;
|
if (EL.hasAnyInfo()) return EL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4553,24 +4567,24 @@ ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpInst::ICMP_SLT: {
|
case ICmpInst::ICMP_SLT: {
|
||||||
ExitLimit EL = HowManyLessThans(LHS, RHS, L, true);
|
ExitLimit EL = HowManyLessThans(LHS, RHS, L, true, IsSubExpr);
|
||||||
if (EL.hasAnyInfo()) return EL;
|
if (EL.hasAnyInfo()) return EL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpInst::ICMP_SGT: {
|
case ICmpInst::ICMP_SGT: {
|
||||||
ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
|
ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
|
||||||
getNotSCEV(RHS), L, true);
|
getNotSCEV(RHS), L, true, IsSubExpr);
|
||||||
if (EL.hasAnyInfo()) return EL;
|
if (EL.hasAnyInfo()) return EL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpInst::ICMP_ULT: {
|
case ICmpInst::ICMP_ULT: {
|
||||||
ExitLimit EL = HowManyLessThans(LHS, RHS, L, false);
|
ExitLimit EL = HowManyLessThans(LHS, RHS, L, false, IsSubExpr);
|
||||||
if (EL.hasAnyInfo()) return EL;
|
if (EL.hasAnyInfo()) return EL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpInst::ICMP_UGT: {
|
case ICmpInst::ICMP_UGT: {
|
||||||
ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
|
ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
|
||||||
getNotSCEV(RHS), L, false);
|
getNotSCEV(RHS), L, false, IsSubExpr);
|
||||||
if (EL.hasAnyInfo()) return EL;
|
if (EL.hasAnyInfo()) return EL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -5439,7 +5453,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) {
|
|||||||
/// effectively V != 0. We know and take advantage of the fact that this
|
/// effectively V != 0. We know and take advantage of the fact that this
|
||||||
/// expression only being used in a comparison by zero context.
|
/// expression only being used in a comparison by zero context.
|
||||||
ScalarEvolution::ExitLimit
|
ScalarEvolution::ExitLimit
|
||||||
ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) {
|
ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr) {
|
||||||
// If the value is a constant
|
// If the value is a constant
|
||||||
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
|
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
|
||||||
// If the value is already zero, the branch will execute zero times.
|
// If the value is already zero, the branch will execute zero times.
|
||||||
@@ -5537,19 +5551,20 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the recurrence is known not to wraparound, unsigned divide computes the
|
// If the recurrence is known not to wraparound, unsigned divide computes the
|
||||||
// back edge count. We know that the value will either become zero (and thus
|
// back edge count. (Ideally we would have an "isexact" bit for udiv). We know
|
||||||
// the loop terminates), that the loop will terminate through some other exit
|
// that the value will either become zero (and thus the loop terminates), that
|
||||||
// condition first, or that the loop has undefined behavior. This means
|
// the loop will terminate through some other exit condition first, or that
|
||||||
// we can't "miss" the exit value, even with nonunit stride.
|
// the loop has undefined behavior. This means we can't "miss" the exit
|
||||||
|
// value, even with nonunit stride.
|
||||||
//
|
//
|
||||||
// FIXME: Prove that loops always exhibits *acceptable* undefined
|
// This is only valid for expressions that directly compute the loop exit. It
|
||||||
// behavior. Loops must exhibit defined behavior until a wrapped value is
|
// is invalid for subexpressions in which the loop may exit through this
|
||||||
// actually used. So the trip count computed by udiv could be smaller than the
|
// branch even if this subexpression is false. In that case, the trip count
|
||||||
// number of well-defined iterations.
|
// computed by this udiv could be smaller than the number of well-defined
|
||||||
if (AddRec->getNoWrapFlags(SCEV::FlagNW)) {
|
// iterations.
|
||||||
// FIXME: We really want an "isexact" bit for udiv.
|
if (!IsSubExpr && AddRec->getNoWrapFlags(SCEV::FlagNW))
|
||||||
return getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
|
return getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
|
||||||
}
|
|
||||||
// Then, try to solve the above equation provided that Start is constant.
|
// Then, try to solve the above equation provided that Start is constant.
|
||||||
if (const SCEVConstant *StartC = dyn_cast<SCEVConstant>(Start))
|
if (const SCEVConstant *StartC = dyn_cast<SCEVConstant>(Start))
|
||||||
return SolveLinEquationWithOverflow(StepC->getValue()->getValue(),
|
return SolveLinEquationWithOverflow(StepC->getValue()->getValue(),
|
||||||
@@ -6315,9 +6330,14 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start,
|
|||||||
/// HowManyLessThans - Return the number of times a backedge containing the
|
/// HowManyLessThans - Return the number of times a backedge containing the
|
||||||
/// specified less-than comparison will execute. If not computable, return
|
/// specified less-than comparison will execute. If not computable, return
|
||||||
/// CouldNotCompute.
|
/// CouldNotCompute.
|
||||||
|
///
|
||||||
|
/// @param IsSubExpr is true when the LHS < RHS condition does not directly
|
||||||
|
/// control the branch. In this case, we can only compute an iteration count for
|
||||||
|
/// a subexpression that cannot overflow before evaluating true.
|
||||||
ScalarEvolution::ExitLimit
|
ScalarEvolution::ExitLimit
|
||||||
ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
||||||
const Loop *L, bool isSigned) {
|
const Loop *L, bool isSigned,
|
||||||
|
bool IsSubExpr) {
|
||||||
// Only handle: "ADDREC < LoopInvariant".
|
// Only handle: "ADDREC < LoopInvariant".
|
||||||
if (!isLoopInvariant(RHS, L)) return getCouldNotCompute();
|
if (!isLoopInvariant(RHS, L)) return getCouldNotCompute();
|
||||||
|
|
||||||
@@ -6326,10 +6346,12 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
|||||||
return getCouldNotCompute();
|
return getCouldNotCompute();
|
||||||
|
|
||||||
// Check to see if we have a flag which makes analysis easy.
|
// Check to see if we have a flag which makes analysis easy.
|
||||||
bool NoWrap = isSigned ?
|
bool NoWrap = false;
|
||||||
AddRec->getNoWrapFlags((SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNW)) :
|
if (!IsSubExpr) {
|
||||||
AddRec->getNoWrapFlags((SCEV::NoWrapFlags)(SCEV::FlagNUW | SCEV::FlagNW));
|
NoWrap = AddRec->getNoWrapFlags(
|
||||||
|
(SCEV::NoWrapFlags)(((isSigned ? SCEV::FlagNSW : SCEV::FlagNUW))
|
||||||
|
| SCEV::FlagNW));
|
||||||
|
}
|
||||||
if (AddRec->isAffine()) {
|
if (AddRec->isAffine()) {
|
||||||
unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
|
unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
|
||||||
const SCEV *Step = AddRec->getStepRecurrence(*this);
|
const SCEV *Step = AddRec->getStepRecurrence(*this);
|
||||||
|
Reference in New Issue
Block a user