diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 6e506174cfb1..e7bb9ab80c20 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -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(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: diff --git a/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll b/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll new file mode 100644 index 000000000000..830a40295acd --- /dev/null +++ b/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll @@ -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 +}