diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1480,7 +1480,17 @@ Pred = CmpInst::getInversePredicate(Pred); // Get the knownbits implied by the incoming phi condition. auto CR = ConstantRange::makeExactICmpRegion(Pred, *RHSC); - Known2 = Known2.unionWith(CR.toKnownBits()); + KnownBits KnownUnion = Known2.unionWith(CR.toKnownBits()); + // We can have conflicts here if we are analyzing deadcode (its + // impossible for us reach this BB based the icmp). + if (KnownUnion.hasConflict()) { + // No reason to continue analyzing in a known dead region, so + // just resetAll and break. This will cause us to also exit the + // outer loop. + Known.resetAll(); + break; + } + Known2 = KnownUnion; } } } diff --git a/llvm/test/Analysis/ValueTracking/knownbits-phi-deadcode.ll b/llvm/test/Analysis/ValueTracking/knownbits-phi-deadcode.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/knownbits-phi-deadcode.ll @@ -0,0 +1,72 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt -O1 -S < %s | FileCheck %s +; This reduced testcase from pr65022. We are only testing that is doesn't crash. + +@b = internal global i32 1 + +define void @f(i32 %spec.select, ptr %c, i1 %tobool.not) { +; CHECK-LABEL: define void @f +; CHECK-SAME: (i32 [[SPEC_SELECT:%.*]], ptr nocapture writeonly [[C:%.*]], i1 [[TOBOOL_NOT:%.*]]) local_unnamed_addr { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TOBOOL2_NOT:%.*]] = icmp eq i32 [[SPEC_SELECT]], 0 +; CHECK-NEXT: br label [[L:%.*]] +; CHECK: L: +; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_THEN1:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, ptr [[C]], align 4 +; CHECK-NEXT: br label [[IF_THEN1]] +; CHECK: if.then1: +; CHECK-NEXT: br i1 [[TOBOOL2_NOT]], label [[FOR_END:%.*]], label [[IF_THEN3:%.*]] +; CHECK: if.then3: +; CHECK-NEXT: tail call void (...) @e() +; CHECK-NEXT: br label [[L]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + br label %L + +L: ; preds = %while.cond, %if.then3, %entry + %i.0 = phi i32 [ 0, %entry ], [ %i.0, %if.then3 ], [ 1, %while.cond ] + br i1 %tobool.not, label %if.end, label %if.then + +if.then: ; preds = %L + store i32 0, ptr %c, align 4 + br label %if.end + +if.end: ; preds = %if.then, %L + %0 = load i32, ptr @b, align 4 + %not = xor i32 %0, 1 + %cmp = icmp sgt i32 %0, -1 + br i1 %cmp, label %if.then1, label %while.cond + +if.then1: ; preds = %if.end + %tobool2.not = icmp eq i32 %spec.select, 0 + br i1 %tobool2.not, label %while.cond, label %if.then3 + +if.then3: ; preds = %if.then1 + call void(...) @e() + br label %L + +while.cond: ; preds = %if.then1, %if.end + %h.02 = phi i32 [ 0, %if.then1 ], [ %not, %if.end ] + %tobool7.not = icmp eq i32 %h.02, 0 + %spec.select3 = select i1 %tobool7.not, i32 %i.0, i32 %spec.select + %tobool10.not = icmp eq i32 %spec.select3, 0 + br i1 %tobool10.not, label %for.cond, label %L + +for.cond: ; preds = %for.inc, %while.cond + %1 = phi i32 [ %inc, %for.inc ], [ %spec.select, %while.cond ] + %tobool13.not = icmp eq i32 %1, 0 + br i1 %tobool13.not, label %for.end, label %for.inc + +for.inc: ; preds = %for.cond + %inc = add i32 %1, 1 + store i32 %inc, ptr @b, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +declare void @e(...)