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 @@ -675,10 +675,11 @@ } // Handle Cast instructions. Only see through Cast when the source operand is - // PHI or Cmp to save the compilation time. + // PHI, Cmp, or Freeze to save the compilation time. if (CastInst *CI = dyn_cast(I)) { Value *Source = CI->getOperand(0); - if (!isa(Source) && !isa(Source)) + if (!isa(Source) && !isa(Source) && + !isa(Source)) return false; ComputeValueKnownInPredecessorsImpl(Source, BB, Result, Preference, RecursionSet, CxtI); @@ -692,6 +693,22 @@ 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) && + !isa(Source)) + return false; + ComputeValueKnownInPredecessorsImpl(Source, BB, Result, Preference, + RecursionSet, CxtI); + + erase_if(Result, [](auto &Pair) { + return !isGuaranteedNotToBeUndefOrPoison(Pair.first); + }); + + 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,24 +42,21 @@ define i32 @test1_cast(i1 %cond) { ; CHECK-LABEL: @test1_cast( -; 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: [[A0:%.*]] = phi i32 [ 1, [[T1]] ], [ 0, [[F1]] ] -; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] -; CHECK-NEXT: [[A:%.*]] = trunc i32 [[A0]] to i1 +; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() +; CHECK-NEXT: [[A:%.*]] = trunc i32 0 to i1 ; CHECK-NEXT: [[A_FR:%.*]] = freeze i1 [[A]] -; CHECK-NEXT: br i1 [[A_FR]], label [[T2:%.*]], label [[F2:%.*]] +; CHECK-NEXT: br i1 [[A_FR]], label [[T2]], label [[F2:%.*]] ; CHECK: T2: +; CHECK-NEXT: [[B5:%.*]] = phi i32 [ [[V1]], [[MERGE_THREAD]] ], [ [[V2]], [[MERGE]] ] ; CHECK-NEXT: call void @f3() -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[B5]] ; CHECK: F2: -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[V2]] ; br i1 %cond, label %T1, label %F1 @@ -97,24 +85,21 @@ define i32 @test1_cast2(i1 %cond) { ; CHECK-LABEL: @test1_cast2( -; 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: [[A0:%.*]] = phi i32 [ 1, [[T1]] ], [ 0, [[F1]] ] -; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ] -; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0]] +; CHECK-NEXT: [[V2:%.*]] = call i32 @f2() +; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 0 ; CHECK-NEXT: [[A_FR:%.*]] = trunc i32 [[A0_FR]] to i1 -; CHECK-NEXT: br i1 [[A_FR]], label [[T2:%.*]], label [[F2:%.*]] +; CHECK-NEXT: br i1 [[A_FR]], label [[T2]], label [[F2:%.*]] ; CHECK: T2: +; CHECK-NEXT: [[B5:%.*]] = phi i32 [ [[V1]], [[MERGE_THREAD]] ], [ [[V2]], [[MERGE]] ] ; CHECK-NEXT: call void @f3() -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[B5]] ; CHECK: F2: -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: ret i32 [[V2]] ; br i1 %cond, label %T1, label %F1 @@ -143,23 +128,20 @@ define i32 @test1_undef(i1 %cond) { ; CHECK-LABEL: @test1_undef( -; 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]] ], [ undef, [[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 undef +; 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 @@ -187,23 +169,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