diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 34c4f7106c4bf..493eb08bb9b05 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -551,8 +551,12 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv, // The context comes first, but they're both in the same block. // Make sure there is nothing in between that might interrupt // the control flow, not even CxtI itself. + // We limit the scan distance between the assume and its context instruction + // to avoid a compile-time explosion. This limit is chosen arbitrarily, so + // it can be adjusted if needed (could be turned into a cl::opt). + unsigned ScanLimit = 15; for (BasicBlock::const_iterator I(CxtI), IE(Inv); I != IE; ++I) - if (!isGuaranteedToTransferExecutionToSuccessor(&*I)) + if (!isGuaranteedToTransferExecutionToSuccessor(&*I) || --ScanLimit == 0) return false; return !isEphemeralValueOf(Inv, CxtI); diff --git a/llvm/test/Transforms/LoopUnroll/assume-timeout.ll b/llvm/test/Transforms/LoopUnroll/assume-timeout.ll new file mode 100644 index 0000000000000..01aeaa09857ad --- /dev/null +++ b/llvm/test/Transforms/LoopUnroll/assume-timeout.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -loop-unroll -unroll-threshold=300 -S < %s | FileCheck %s + +; This test caused a compile-time explosion in ValueTracking +; because we cloned the assume value and call greatly and +; then spent far too long analyzing those. + +define void @PR49171(i32 %arg) { +; CHECK-LABEL: @PR49171( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[ASSUME:%.*]] = icmp eq i32 0, [[ARG:%.*]] +; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv2 = phi i32 [ 0, %entry ], [ %arg, %loop ] + %assume = icmp eq i32 %iv2, %arg + call void @llvm.assume(i1 %assume) + %iv.inc = add nuw nsw i32 %iv, 1 + %exitcond = icmp eq i32 %iv.inc, 50 ; Increase me! + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +declare void @llvm.assume(i1)