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 @@ -692,6 +692,24 @@ return true; } + // Handle Freeze instructions, in a manner similar to Cast. + if (FreezeInst *FI = dyn_cast(I)) { + Value *Source = FI->getOperand(0); + if (!isa(Source) && !isa(Source)) + return false; + ComputeValueKnownInPredecessorsImpl(Source, BB, Result, Preference, + RecursionSet, CxtI); + + for (unsigned i = 0; i < Result.size(); ++i) { + if (!isGuaranteedNotToBeUndefOrPoison(Result[i].first)) { + Result.erase(Result.begin() + i); + i--; + } + } + + return !Result.empty(); + } + // Handle some boolean conditions. if (I->getType()->getPrimitiveSizeInBits() == 1) { assert(Preference == WantInteger && "One-bit non-integer type?"); diff --git a/llvm/test/Transforms/JumpThreading/freeze.ll b/llvm/test/Transforms/JumpThreading/freeze.ll --- a/llvm/test/Transforms/JumpThreading/freeze.ll +++ b/llvm/test/Transforms/JumpThreading/freeze.ll @@ -7,23 +7,14 @@ define i32 @test1(i1 %cond) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[T1:%.*]], label [[F1:%.*]] -; CHECK: T1: -; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() -; CHECK-NEXT: br label [[MERGE:%.*]] -; CHECK: F1: -; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() -; CHECK-NEXT: br label [[MERGE]] -; CHECK: Merge: -; CHECK-NEXT: [[A:%.*]] = phi i1 [ true, [[T1]] ], [ false, [[F1]] ] -; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] -; CHECK-NEXT: [[A_FR:%.*]] = freeze i1 [[A]] -; CHECK-NEXT: br i1 [[A_FR]], label [[T2:%.*]], label [[F2:%.*]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[T2:%.*]], label [[F2:%.*]] ; CHECK: T2: +; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() ; CHECK-NEXT: call void @f3() -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[V1]] ; CHECK: F2: -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() +; CHECK-NEXT: ret i32 [[V2]] ; br i1 %cond, label %T1, label %F1 @@ -51,23 +42,20 @@ define i32 @test2(i1 %cond, i1 %cond2) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[T1:%.*]], label [[F1:%.*]] -; CHECK: T1: +; CHECK-NEXT: br i1 [[COND:%.*]], label [[MERGE_THREAD:%.*]], label [[MERGE:%.*]] +; CHECK: Merge.thread: ; CHECK-NEXT: [[V1:%.*]] = call i32 @f1() -; CHECK-NEXT: br label [[MERGE:%.*]] -; CHECK: F1: -; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() -; CHECK-NEXT: br label [[MERGE]] +; CHECK-NEXT: br label [[T2:%.*]] ; CHECK: Merge: -; CHECK-NEXT: [[A:%.*]] = phi i1 [ true, [[T1]] ], [ [[COND2:%.*]], [[F1]] ] -; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] -; CHECK-NEXT: [[A_FR:%.*]] = freeze i1 [[A]] -; CHECK-NEXT: br i1 [[A_FR]], label [[T2:%.*]], label [[F2:%.*]] +; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() +; CHECK-NEXT: [[A_FR:%.*]] = freeze i1 [[COND2:%.*]] +; CHECK-NEXT: br i1 [[A_FR]], label [[T2]], label [[F2:%.*]] ; CHECK: T2: +; CHECK-NEXT: [[B4:%.*]] = phi i32 [ [[V1]], [[MERGE_THREAD]] ], [ [[V2]], [[MERGE]] ] ; CHECK-NEXT: call void @f3() -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[B4]] ; CHECK: F2: -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[V2]] ; br i1 %cond, label %T1, label %F1