diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -654,22 +654,25 @@ Instruction *I = dyn_cast(V); if (!I || I->getParent() != BB) { - // Okay, if this is a live-in value, see if it has a known value at the end - // of any of our predecessors. - // - // FIXME: This should be an edge property, not a block end property. - /// TODO: Per PR2563, we could infer value range information about a - /// predecessor based on its terminator. - // - // FIXME: change this to use the more-rich 'getPredicateOnEdge' method if - // "I" is a non-local compare-with-a-constant instruction. This would be - // able to handle value inequalities better, for example if the compare is - // "X < 4" and "X < 3" is known true but "X < 4" itself is not available. - // Perhaps getConstantOnEdge should be smart enough to do this? + // Okay, if this is a live-in value, see if it has a known value at the any + // edge from our predecessors. for (BasicBlock *P : predecessors(BB)) { + using namespace PatternMatch; // If the value is known by LazyValueInfo to be a constant in a // predecessor, use that information to try to thread this block. Constant *PredCst = LVI->getConstantOnEdge(V, P, BB, CxtI); + // If I is a non-local compare-with-constant instruction, use more-rich + // 'getPredicateOnEdge' method. This would be able to handle value + // inequalities better, for example if the compare is "X < 4" and "X < 3" + // is known true but "X < 4" itself is not available. + CmpInst::Predicate Pred; + Value *Val; + Constant *Cst; + if (!PredCst && match(V, m_Cmp(Pred, m_Value(Val), m_Constant(Cst)))) { + auto Res = LVI->getPredicateOnEdge(Pred, Val, Cst, P, BB, CxtI); + if (Res != LazyValueInfo::Unknown) + PredCst = ConstantInt::getBool(V->getContext(), Res); + } if (Constant *KC = getKnownConstant(PredCst, Preference)) Result.emplace_back(KC, P); } diff --git a/llvm/test/Transforms/JumpThreading/range-compare.ll b/llvm/test/Transforms/JumpThreading/range-compare.ll --- a/llvm/test/Transforms/JumpThreading/range-compare.ll +++ b/llvm/test/Transforms/JumpThreading/range-compare.ll @@ -123,3 +123,42 @@ ret void } +; Make sure we thread the false side of the first if to the end of the function +; (case with non-local comparisions). +define void @test4(i32 %x) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 9 +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], -3 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[X_OFF]], 5 +; CHECK-NEXT: br i1 [[CMP1]], label [[IF_END:%.*]], label [[IF_END4:%.*]] +; CHECK: if.end: +; CHECK-NEXT: call void (...) @bar() +; CHECK-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4]] +; CHECK: if.then3: +; CHECK-NEXT: call void (...) @baz() +; CHECK-NEXT: br label [[IF_END4]] +; CHECK: if.end4: +; CHECK-NEXT: ret void +; +entry: + %cmp1 = icmp slt i32 %x, 9 + %x.off = add i32 %x, -3 + %cmp2 = icmp ult i32 %x.off, 5 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %entry + call void (...) @bar() + br label %if.end + +if.end: ; preds = %if.then, %entry + br i1 %cmp2, label %if.then3, label %if.end4 + +if.then3: ; preds = %if.end + call void (...) @baz() + br label %if.end4 + +if.end4: ; preds = %if.then3, %if.end + ret void +} +