Index: llvm/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/lib/Analysis/LoopInfo.cpp +++ llvm/lib/Analysis/LoopInfo.cpp @@ -210,14 +210,34 @@ if (!InitialIVValue || !StepInst) return std::nullopt; - const SCEV *Step = IndDesc.getStep(); - Value *StepInstOp1 = StepInst->getOperand(1); - Value *StepInstOp0 = StepInst->getOperand(0); +// We need to make sure we get the right step in case the stepinst is a sub + // First, try to get the step as a constant int. If that doesn't work, get it + // as a scev, but it needs to be inverted if the stepinst is a sub! Value *StepValue = nullptr; - if (SE.getSCEV(StepInstOp1) == Step) - StepValue = StepInstOp1; - else if (SE.getSCEV(StepInstOp0) == Step) - StepValue = StepInstOp0; + if (ConstantInt *StepConst = IndDesc.getConstIntStepValue()) { + StepValue = StepConst; + } else { + const SCEV *Step = IndDesc.getStep(); + // If the stepinst is a subtract, the SCEV returned for Step will be a + // negative number. This will cause the below if/elseif to fail because the + // operand in the sub instruction will be a positive number. In this case, + // we should check when we have a sub and generate a new SCEV for step that + // is equal to -1 * Step. + if (StepInst->getOpcode() == Instruction::Sub) { + const SCEV *MinusOneSCEV = + SE.getConstant(Type::getInt32Ty(SE.getContext()), -1, true); + const SCEV *InvertedStep = SE.getMulExpr(MinusOneSCEV, Step); + Step = InvertedStep; + } + Value *StepInstOp1 = StepInst->getOperand(1); + Value *StepInstOp0 = StepInst->getOperand(0); + if (SE.getSCEV(StepInstOp1) == Step) + StepValue = StepInstOp1; + else if (SE.getSCEV(StepInstOp0) == Step) + StepValue = StepInstOp0; + else + return std::nullopt; + } Value *FinalIVValue = findFinalIVValue(L, IndVar, *StepInst); if (!FinalIVValue) Index: llvm/unittests/Analysis/LoopInfoTest.cpp =================================================================== --- llvm/unittests/Analysis/LoopInfoTest.cpp +++ llvm/unittests/Analysis/LoopInfoTest.cpp @@ -746,7 +746,7 @@ EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); ConstantInt *StepValue = dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_EQ(StepValue, nullptr); + EXPECT_TRUE(StepValue && StepValue->getSExtValue() == -1); ConstantInt *FinalIVValue = dyn_cast(&Bounds->getFinalIVValue()); EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero());