Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -475,6 +475,26 @@ return !Result.empty(); } + // Handle Cast instructions. Only see through Cast when the source operand is + // PHI or Cmp and the source type is i1 to save the compilation time. + if (CastInst *CI = dyn_cast(I)) { + Value *Source = CI->getOperand(0); + if (!Source->getType()->isIntegerTy(1)) + return false; + if (!isa(Source) && !isa(Source)) + return false; + ComputeValueKnownInPredecessors(Source, BB, Result, Preference, Changed, + CxtI); + if (Result.empty()) + return false; + + // Convert the known values. + for (auto &R : Result) + R.first = ConstantExpr::getCast(CI->getOpcode(), R.first, CI->getType()); + + return true; + } + PredValueInfoTy LHSVals, RHSVals; // Handle some boolean conditions. Index: test/Transforms/JumpThreading/basic.ll =================================================================== --- test/Transforms/JumpThreading/basic.ll +++ test/Transforms/JumpThreading/basic.ll @@ -511,9 +511,43 @@ ; CHECK-NEXT: phi i32 } +;;; Verify that we can handle constraint propagation through cast. +define i32 @test17(i1 %cond) { +Entry: +; CHECK-LABEL: @test17( + br i1 %cond, label %Merge, label %F1 + +; CHECK: Entry: +; CHECK-NEXT: br i1 %cond, label %F2, label %Merge + +F1: + %v1 = call i32 @f1() + br label %Merge + +Merge: + %B = phi i32 [0, %Entry], [%v1, %F1] + %M = icmp eq i32 %B, 0 + %M1 = zext i1 %M to i32 + %N = icmp eq i32 %M1, 0 + br i1 %N, label %T2, label %F2 + +; CHECK: Merge: +; CHECK-NOT: phi +; CHECK-NEXT: %v1 = call i32 @f1() + +T2: + %Q = call i32 @f2() + ret i32 %Q + +F2: + ret i32 %B +; CHECK: F2: +; CHECK-NEXT: phi i32 +} + ;;; Just check that ComputeValueKnownInPredecessors() does not return true with ;;; no values and triggers the assert in ProcessThreadableEdges(). -define i32 @test17() { +define i32 @test18() { entry: %A = add i32 0, 1 %B = icmp eq i32 %A, 0