diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1048,7 +1048,9 @@ BasicBlock *NonConstBB = nullptr; for (unsigned i = 0; i != NumPHIValues; ++i) { Value *InVal = PN->getIncomingValue(i); - if (isa(InVal) && !isa(InVal)) + // If I is a freeze instruction, count undef as a non-constant. + if (isa(InVal) && !isa(InVal) && + (!isa(I) || isGuaranteedNotToBeUndefOrPoison(InVal))) continue; if (isa(InVal)) return nullptr; // Itself a phi. @@ -1141,6 +1143,15 @@ Builder); NewPN->addIncoming(InV, PN->getIncomingBlock(i)); } + } else if (auto *FI = dyn_cast(&I)) { + for (unsigned i = 0; i != NumPHIValues; ++i) { + Value *InV; + if (NonConstBB == PN->getIncomingBlock(i)) + InV = Builder.CreateFreeze(PN->getIncomingValue(i), "phi.fr"); + else + InV = PN->getIncomingValue(i); + NewPN->addIncoming(InV, PN->getIncomingBlock(i)); + } } else { CastInst *CI = cast(&I); Type *RetTy = CI->getType(); @@ -3370,6 +3381,12 @@ if (Value *V = SimplifyFreezeInst(Op0, SQ.getWithInstruction(&I))) return replaceInstUsesWith(I, V); + // freeze (phi const, x) --> phi const, (freeze x) + if (auto *PN = dyn_cast(Op0)) { + if (Instruction *NV = foldOpIntoPhi(I, PN)) + return NV; + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/freeze-phi.ll b/llvm/test/Transforms/InstCombine/freeze-phi.ll --- a/llvm/test/Transforms/InstCombine/freeze-phi.ll +++ b/llvm/test/Transforms/InstCombine/freeze-phi.ll @@ -51,11 +51,11 @@ ; CHECK: A: ; CHECK-NEXT: br label [[C:%.*]] ; CHECK: B: +; CHECK-NEXT: [[PHI_FR:%.*]] = freeze <2 x i32> ; CHECK-NEXT: br label [[C]] ; CHECK: C: -; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ , [[A]] ], [ , [[B]] ] -; CHECK-NEXT: [[Y_FR:%.*]] = freeze <2 x i32> [[Y]] -; CHECK-NEXT: ret <2 x i32> [[Y_FR]] +; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ , [[A]] ], [ [[PHI_FR]], [[B]] ] +; CHECK-NEXT: ret <2 x i32> [[Y]] ; br i1 %cond, label %A, label %B A: @@ -74,11 +74,11 @@ ; CHECK: A: ; CHECK-NEXT: br label [[C:%.*]] ; CHECK: B: +; CHECK-NEXT: [[PHI_FR:%.*]] = freeze i32 [[X:%.*]] ; CHECK-NEXT: br label [[C]] ; CHECK: C: -; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 0, [[A]] ], [ [[X:%.*]], [[B]] ] -; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]] -; CHECK-NEXT: ret i32 [[Y_FR]] +; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 0, [[A]] ], [ [[PHI_FR]], [[B]] ] +; CHECK-NEXT: ret i32 [[Y]] ; br i1 %cond, label %A, label %B A: @@ -154,15 +154,15 @@ ; CHECK-NEXT: i8 1, label [[C:%.*]] ; CHECK-NEXT: ] ; CHECK: A: +; CHECK-NEXT: [[PHI_FR:%.*]] = freeze i32 undef ; CHECK-NEXT: br label [[D:%.*]] ; CHECK: B: ; CHECK-NEXT: br label [[D]] ; CHECK: C: ; CHECK-NEXT: br label [[D]] ; CHECK: D: -; CHECK-NEXT: [[Y:%.*]] = phi i32 [ undef, [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] -; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]] -; CHECK-NEXT: ret i32 [[Y_FR]] +; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[PHI_FR]], [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] +; CHECK-NEXT: ret i32 [[Y]] ; switch i8 %cond, label %A [ i8 0, label %B @@ -189,15 +189,15 @@ ; CHECK-NEXT: i8 1, label [[C:%.*]] ; CHECK-NEXT: ] ; CHECK: A: +; CHECK-NEXT: [[PHI_FR:%.*]] = freeze i32 ptrtoint (i8* getelementptr inbounds (i8, i8* @glb, i64 2) to i32) ; CHECK-NEXT: br label [[D:%.*]] ; CHECK: B: ; CHECK-NEXT: br label [[D]] ; CHECK: C: ; CHECK-NEXT: br label [[D]] ; CHECK: D: -; CHECK-NEXT: [[Y:%.*]] = phi i32 [ ptrtoint (i8* getelementptr inbounds (i8, i8* @glb, i64 2) to i32), [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] -; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]] -; CHECK-NEXT: ret i32 [[Y_FR]] +; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[PHI_FR]], [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] +; CHECK-NEXT: ret i32 [[Y]] ; switch i8 %cond, label %A [ i8 0, label %B