diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -7289,7 +7289,8 @@ if (auto BO = MatchBinaryOp(U, DT)) { bool IsConstArg = isa(BO->RHS); switch (BO->Opcode) { - case Instruction::Add: { + case Instruction::Add: + case Instruction::Mul: { // For additions and multiplications, traverse add/mul chains for which we // can potentially create a single SCEV, to reduce the number of // get{Add,Mul}Expr calls. @@ -7302,30 +7303,24 @@ } Ops.push_back(BO->RHS); auto NewBO = MatchBinaryOp(BO->LHS, DT); - if (!NewBO || (NewBO->Opcode != Instruction::Add && - NewBO->Opcode != Instruction::Sub)) { + if (!NewBO || + (U->getOpcode() == Instruction::Add && + (NewBO->Opcode != Instruction::Add && + NewBO->Opcode != Instruction::Sub)) || + (U->getOpcode() == Instruction::Mul && + NewBO->Opcode != Instruction::Mul)) { Ops.push_back(BO->LHS); break; } - BO = NewBO; - } while (true); - return nullptr; - } - - case Instruction::Mul: { - do { - if (BO->Op) { - if (BO->Op != V && getExistingSCEV(BO->Op)) { - Ops.push_back(BO->Op); + // CreateSCEV calls getNoWrapFlagsFromUB, which under certain conditions + // requires a SCEV for the LHS. + if (NewBO->Op && (NewBO->IsNSW || NewBO->IsNUW)) { + if (auto *I = dyn_cast(NewBO->Op); + I && programUndefinedIfPoison(I)) { + Ops.push_back(BO->LHS); break; } } - Ops.push_back(BO->RHS); - auto NewBO = MatchBinaryOp(BO->LHS, DT); - if (!NewBO || NewBO->Opcode != Instruction::Mul) { - Ops.push_back(BO->LHS); - break; - } BO = NewBO; } while (true); return nullptr;