Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -121,6 +121,12 @@ cl::desc("Verify no dangling value in ScalarEvolution's " "ExprValueMap (slow)")); +static cl::opt MaxMulOpsToInline( + "scev-max-mulops-inline", cl::Hidden, + cl::desc("Maximum number of multiplication operands to be " + "inlined to current multiplication SCEV"), + cl::init(1000)); + //===----------------------------------------------------------------------===// // SCEV class definitions //===----------------------------------------------------------------------===// @@ -2516,6 +2522,8 @@ if (Idx < Ops.size()) { bool DeletedMul = false; while (const SCEVMulExpr *Mul = dyn_cast(Ops[Idx])) { + if (Mul->getNumOperands() > MaxMulOpsToInline) + break; // If we have an mul, expand the mul operands onto the end of the operands // list. Ops.erase(Ops.begin()+Idx); Index: test/Analysis/ScalarEvolution/max-mulops-inline.ll =================================================================== --- test/Analysis/ScalarEvolution/max-mulops-inline.ll +++ test/Analysis/ScalarEvolution/max-mulops-inline.ll @@ -0,0 +1,46 @@ +; RUN: opt -analyze -scalar-evolution -scev-max-mulops-inline=1 < %s | FileCheck --check-prefix=CHECK1 %s +; RUN: opt -analyze -scalar-evolution -scev-max-mulops-inline=10 < %s | FileCheck --check-prefix=CHECK10 %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@a = local_unnamed_addr global i32 0, align 4 +@b = local_unnamed_addr global i32 0, align 4 +@c = local_unnamed_addr global i32 0, align 4 + +; Function Attrs: norecurse nounwind uwtable +define i32 @main() local_unnamed_addr { + +; CHECK1: %mul.1 = mul nsw i32 %mul, %mul +; CHECK1: --> ((%mul.lcssa5 * %mul.lcssa5) * (%mul.lcssa5 * %mul.lcssa5)) + +; CHECK10: %mul.1 = mul nsw i32 %mul, %mul +; CHECK10: --> (%mul.lcssa5 * %mul.lcssa5 * %mul.lcssa5 * %mul.lcssa5) + +entry: + %a.promoted4 = load i32, i32* @a, align 4 + br label %for.cond1.preheader + +for.cond1.preheader: ; preds = %for.body3, %entry + %mul.lcssa5 = phi i32 [ %a.promoted4, %entry ], [ %mul.5, %for.body3 ] + %i.03 = phi i32 [ 0, %entry ], [ %inc5, %for.body3 ] + br label %for.body3 + +for.body3: ; preds = %for.cond1.preheader + %mul = mul nsw i32 %mul.lcssa5, %mul.lcssa5 + %mul.1 = mul nsw i32 %mul, %mul + %mul.2 = mul nsw i32 %mul.1, %mul.1 + %mul.3 = mul nsw i32 %mul.2, %mul.2 + %mul.4 = mul nsw i32 %mul.3, %mul.3 + %mul.5 = mul nsw i32 %mul.4, %mul.4 + %inc5 = add nsw i32 %i.03, 1 + %cmp = icmp slt i32 %inc5, 10 + br i1 %cmp, label %for.cond1.preheader, label %for.end6 + +for.end6: ; preds = %for.body3 + %mul.lcssa.lcssa = phi i32 [ %mul.5, %for.body3 ] + %inc.lcssa.lcssa = phi i32 [ 6, %for.body3 ] + store i32 %mul.lcssa.lcssa, i32* @a, align 4 + store i32 %inc.lcssa.lcssa, i32* @b, align 4 + ret i32 0 +}