From 7ae5d00afaf39fae78e411cb44f665e1dc52b356 Mon Sep 17 00:00:00 2001 From: Johannes Reifferscheid Date: Wed, 3 Aug 2022 07:07:55 +0200 Subject: Fix a stack overflow in ScalarEvolution. Unfortunately, this overflow is extremely hard to reproduce reliably (in fact, I was unable to do so). The issue is that: - getOperandsToCreate sometimes skips creating an SCEV for the LHS - then, createSCEV is called for the BinaryOp - ... which calls getNoWrapFlagsFromUB - ... which under certain circumstances calls isSCEVExprNeverPoison - ... which under certain circumstances requires the SCEVs of all operands For certain deep dependency trees, this causes a stack overflow. Reviewed By: bkramer, fhahn Differential Revision: https://reviews.llvm.org/D129745 --- llvm/lib/Analysis/ScalarEvolution.cpp | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'llvm') diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 5777592..f5f5e67 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -7289,7 +7289,8 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl &Ops) { 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 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl &Ops) { } 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; -- cgit v1.1