[InstCombine] Opt phi(freeze(undef), C) -> phi(C, C) (#161181)
Try to choose a value for freeze that enables the PHI to be replaced with its input constants if they are equal.
This commit is contained in:
parent
5baf1c1464
commit
69586331e8
@ -5169,6 +5169,7 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
|
||||
// - or: pick -1
|
||||
// - select's condition: if the true value is constant, choose it by making
|
||||
// the condition true.
|
||||
// - phi: pick the common constant across operands
|
||||
// - default: pick 0
|
||||
//
|
||||
// Note that this transform is intentionally done here rather than
|
||||
@ -5179,9 +5180,32 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
|
||||
// TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid
|
||||
// duplicating logic for binops at least.
|
||||
auto getUndefReplacement = [&](Type *Ty) {
|
||||
Value *BestValue = nullptr;
|
||||
auto pickCommonConstantFromPHI = [](PHINode &PN) -> Value * {
|
||||
// phi(freeze(undef), C, C). Choose C for freeze so the PHI can be
|
||||
// removed.
|
||||
Constant *BestValue = nullptr;
|
||||
for (Value *V : PN.incoming_values()) {
|
||||
if (match(V, m_Freeze(m_Undef())))
|
||||
continue;
|
||||
|
||||
Constant *C = dyn_cast<Constant>(V);
|
||||
if (!C)
|
||||
return nullptr;
|
||||
|
||||
if (!isGuaranteedNotToBeUndefOrPoison(C))
|
||||
return nullptr;
|
||||
|
||||
if (BestValue && BestValue != C)
|
||||
return nullptr;
|
||||
|
||||
BestValue = C;
|
||||
}
|
||||
return BestValue;
|
||||
};
|
||||
|
||||
Value *NullValue = Constant::getNullValue(Ty);
|
||||
for (const auto *U : I.users()) {
|
||||
Value *BestValue = nullptr;
|
||||
for (auto *U : I.users()) {
|
||||
Value *V = NullValue;
|
||||
if (match(U, m_Or(m_Value(), m_Value())))
|
||||
V = ConstantInt::getAllOnesValue(Ty);
|
||||
@ -5190,6 +5214,9 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
|
||||
else if (match(U, m_c_Select(m_Specific(&I), m_Value(V)))) {
|
||||
if (!isGuaranteedNotToBeUndefOrPoison(V, &AC, &I, &DT))
|
||||
V = NullValue;
|
||||
} else if (auto *PHI = dyn_cast<PHINode>(U)) {
|
||||
if (Value *MaybeV = pickCommonConstantFromPHI(*PHI))
|
||||
V = MaybeV;
|
||||
}
|
||||
|
||||
if (!BestValue)
|
||||
|
||||
274
llvm/test/Transforms/InstCombine/in-freeze-phi.ll
Normal file
274
llvm/test/Transforms/InstCombine/in-freeze-phi.ll
Normal file
@ -0,0 +1,274 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
||||
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
|
||||
|
||||
define i32 @phi_freeze_same_consts(i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define i32 @phi_freeze_same_consts(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: ret i32 42
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze i32 undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %final
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi i32 [ %f, %bb_freeze ], [ 42, %cA ], [ 42, %cB ]
|
||||
ret i32 %phi
|
||||
}
|
||||
|
||||
define i32 @phi_freeze_mixed_consts(i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define i32 @phi_freeze_mixed_consts(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB_FREEZE]] ], [ 42, %[[CA]] ], [ 7, %[[CB]] ]
|
||||
; CHECK-NEXT: ret i32 [[PHI]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze i32 undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %final
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi i32 [ %f, %bb_freeze ], [ 42, %cA ], [ 7, %cB ]
|
||||
ret i32 %phi
|
||||
}
|
||||
|
||||
define i32 @phi_freeze_with_nonconst_incoming(i32 %x, i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define i32 @phi_freeze_with_nonconst_incoming(
|
||||
; CHECK-SAME: i32 [[X:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB_FREEZE]] ], [ [[X]], %[[CA]] ], [ 13, %[[CB]] ]
|
||||
; CHECK-NEXT: ret i32 [[PHI]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze i32 undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %final
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi i32 [ %f, %bb_freeze ], [ %x, %cA ], [ 13, %cB ]
|
||||
ret i32 %phi
|
||||
}
|
||||
|
||||
define <4 x i8> @phi_freeze_vector(i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define <4 x i8> @phi_freeze_vector(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: ret <4 x i8> splat (i8 9)
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze <4 x i8> undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
|
||||
cA:
|
||||
br label %final
|
||||
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi <4 x i8> [ %f, %bb_freeze ],
|
||||
[<i8 9, i8 9, i8 9, i8 9>, %cA ],
|
||||
[<i8 9, i8 9, i8 9, i8 9>, %cB ]
|
||||
ret <4 x i8> %phi
|
||||
}
|
||||
|
||||
define i32 @multi_use_one_folds_one_not_zero(i1 %c0, i1 %c1, i1 %c2) {
|
||||
; CHECK-LABEL: define i32 @multi_use_one_folds_one_not_zero(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_OTHER3:.*]], label %[[CC1:.*]]
|
||||
; CHECK: [[BB_OTHER3]]:
|
||||
; CHECK-NEXT: br label %[[MID:.*]]
|
||||
; CHECK: [[CC1]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[MID]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[MID]]
|
||||
; CHECK: [[MID]]:
|
||||
; CHECK-NEXT: [[PHI_FOLD:%.*]] = phi i32 [ 0, %[[BB_OTHER3]] ], [ 1, %[[CA]] ], [ 1, %[[CB]] ]
|
||||
; CHECK-NEXT: br i1 [[C2]], label %[[BB_FREEZE2:.*]], label %[[CD:.*]]
|
||||
; CHECK: [[BB_FREEZE2]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER2:.*:]]
|
||||
; CHECK-NEXT: br i1 true, label %[[CA]], label %[[CB]]
|
||||
; CHECK: [[CC:.*:]]
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CD]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: ret i32 [[PHI_FOLD]]
|
||||
;
|
||||
entry:
|
||||
%f = freeze i32 undef
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
bb_freeze:
|
||||
br label %mid
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %mid
|
||||
cB:
|
||||
br label %mid
|
||||
mid:
|
||||
%phi_no_fold = phi i32 [ %f, %bb_freeze ], [ 1, %cA ], [ 1, %cB ]
|
||||
br i1 %c2, label %bb_freeze2, label %cD
|
||||
bb_freeze2:
|
||||
br label %final
|
||||
bb_other2:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cC:
|
||||
br label %final
|
||||
cD:
|
||||
br label %final
|
||||
final:
|
||||
%phi_fold = phi i32 [ %f, %bb_freeze2 ], [ 0, %cC ], [ 0, %cD ]
|
||||
%a = add i32 %phi_fold, %phi_no_fold
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
define i32 @phi_freeze_poison(i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define i32 @phi_freeze_poison(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze i32 undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %final
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi i32 [ %f, %bb_freeze ], [ poison, %cA ], [ poison, %cB ]
|
||||
ret i32 %phi
|
||||
}
|
||||
|
||||
define <2 x i32> @phi_freeze_poison_vec(i1 %c0, i1 %c1) {
|
||||
; CHECK-LABEL: define <2 x i32> @phi_freeze_poison_vec(
|
||||
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
|
||||
; CHECK-NEXT: [[ENTRY:.*:]]
|
||||
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
|
||||
; CHECK: [[BB_FREEZE]]:
|
||||
; CHECK-NEXT: br label %[[FINAL:.*]]
|
||||
; CHECK: [[BB_OTHER]]:
|
||||
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
|
||||
; CHECK: [[CA]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[CB]]:
|
||||
; CHECK-NEXT: br label %[[FINAL]]
|
||||
; CHECK: [[FINAL]]:
|
||||
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i32> [ zeroinitializer, %[[BB_FREEZE]] ], [ <i32 poison, i32 1>, %[[CA]] ], [ <i32 poison, i32 1>, %[[CB]] ]
|
||||
; CHECK-NEXT: ret <2 x i32> [[PHI]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb_freeze, label %bb_other
|
||||
|
||||
bb_freeze:
|
||||
%f = freeze <2 x i32> undef
|
||||
br label %final
|
||||
|
||||
bb_other:
|
||||
br i1 %c1, label %cA, label %cB
|
||||
cA:
|
||||
br label %final
|
||||
cB:
|
||||
br label %final
|
||||
|
||||
final:
|
||||
%phi = phi <2 x i32> [ %f, %bb_freeze ], [ <i32 poison, i32 1>, %cA ], [ <i32 poison, i32 1>, %cB ]
|
||||
ret <2 x i32> %phi
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user