Be more careful when transforming | to +. Patch from Wojciech Matyjewicz.

llvm-svn: 44248
This commit is contained in:
Nick Lewycky 2007-11-20 08:24:44 +00:00
parent 9e823c745d
commit 5b18bd3368
2 changed files with 26 additions and 6 deletions

View File

@ -1484,25 +1484,27 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) {
case Instruction::SDiv:
return SE.getSDivExpr(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1)));
break;
case Instruction::Sub:
return SE.getMinusSCEV(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1)));
case Instruction::Or:
// If the RHS of the Or is a constant, we may have something like:
// X*4+1 which got turned into X*4|1. Handle this as an add so loop
// X*4+1 which got turned into X*4|1. Handle this as an Add so loop
// optimizations will transparently handle this case.
//
// In order for this transformation to be safe, the LHS must be of the
// form X*(2^n) and the Or constant must be less than 2^n.
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
SCEVHandle LHS = getSCEV(I->getOperand(0));
APInt CommonFact(GetConstantFactor(LHS));
assert(!CommonFact.isMinValue() &&
"Common factor should at least be 1!");
if (CommonFact.ugt(CI->getValue())) {
// If the LHS is a multiple that is larger than the RHS, use +.
const APInt &CIVal = CI->getValue();
if (CommonFact.countTrailingZeros() >=
(CIVal.getBitWidth() - CIVal.countLeadingZeros()))
return SE.getAddExpr(LHS,
getSCEV(I->getOperand(1)));
}
}
break;
case Instruction::Xor:

View File

@ -0,0 +1,18 @@
; RUN: llvm-as < %s | opt -analyze -scalar-evolution 2>&1 | grep -e '--> %b'
; PR1810
define void @fun() {
entry:
br label %header
header:
%i = phi i32 [ 1, %entry ], [ %i.next, %body ]
%cond = icmp eq i32 %i, 10
br i1 %cond, label %exit, label %body
body:
%a = mul i32 %i, 5
%b = or i32 %a, 1
%i.next = add i32 %i, 1
br label %header
exit:
ret void
}