Skip to content

Commit b1f9e87

Browse files
committed
[InstCombine] Enable select freeze poison folding when storing value
The non-freeze poison argument to select can be one of the following: global, constant, and noundef arguments. Alive2 test validation: - https://alive2.llvm.org/ce/z/jbtCS6 - https://alive2.llvm.org/ce/z/YFA-5S Refactor replacement of poison elements in constant vectors to use the first non-poison element.
1 parent 397696b commit b1f9e87

File tree

4 files changed

+123
-17
lines changed

4 files changed

+123
-17
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4812,15 +4812,20 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
48124812
//
48134813
// TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid
48144814
// duplicating logic for binops at least.
4815-
auto getUndefReplacement = [&I](Type *Ty) {
4816-
Constant *BestValue = nullptr;
4817-
Constant *NullValue = Constant::getNullValue(Ty);
4815+
auto getUndefReplacement = [&I, &AC = this->AC, &DT = this->DT](Type *Ty) {
4816+
Value *BestValue = nullptr;
4817+
Value *NullValue = Constant::getNullValue(Ty);
48184818
for (const auto *U : I.users()) {
4819-
Constant *C = NullValue;
4819+
Value *C = NullValue;
48204820
if (match(U, m_Or(m_Value(), m_Value())))
48214821
C = ConstantInt::getAllOnesValue(Ty);
48224822
else if (match(U, m_Select(m_Specific(&I), m_Constant(), m_Value())))
48234823
C = ConstantInt::getTrue(Ty);
4824+
else if (match(&I, m_Freeze(m_Poison())) &&
4825+
match(U, m_c_Select(m_Specific(&I), m_Value(C)))) {
4826+
if (!isGuaranteedNotToBeUndefOrPoison(C, &AC, &I, &DT))
4827+
C = NullValue;
4828+
}
48244829

48254830
if (!BestValue)
48264831
BestValue = C;
@@ -4840,10 +4845,26 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
48404845
return replaceInstUsesWith(I, getUndefReplacement(I.getType()));
48414846
}
48424847

4848+
auto getFreezeVectorReplacement = [](Constant *C) -> Constant * {
4849+
Type *Ty = C->getType();
4850+
auto *VTy = dyn_cast<FixedVectorType>(Ty);
4851+
if (!VTy)
4852+
return C;
4853+
unsigned NumElts = VTy->getNumElements();
4854+
Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
4855+
for (unsigned i = 0; i != NumElts; ++i) {
4856+
Constant *EltC = C->getAggregateElement(i);
4857+
if (EltC && !match(EltC, m_Undef())) {
4858+
BestValue = EltC;
4859+
break;
4860+
}
4861+
}
4862+
return Constant::replaceUndefsWith(C, BestValue);
4863+
};
4864+
48434865
Constant *C;
48444866
if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement()) {
4845-
Constant *ReplaceC = getUndefReplacement(I.getType()->getScalarType());
4846-
return replaceInstUsesWith(I, Constant::replaceUndefsWith(C, ReplaceC));
4867+
return replaceInstUsesWith(I, getFreezeVectorReplacement(C));
48474868
}
48484869

48494870
// Replace uses of Op with freeze(Op).

llvm/test/Transforms/InstCombine/freeze-phi.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ define <2 x i32> @vec_undef(i1 %cond) {
5353
; CHECK: B:
5454
; CHECK-NEXT: br label [[C]]
5555
; CHECK: C:
56-
; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ <i32 0, i32 1>, [[A]] ], [ <i32 2, i32 0>, [[B]] ]
56+
; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ <i32 0, i32 1>, [[A]] ], [ splat (i32 2), [[B]] ]
5757
; CHECK-NEXT: ret <2 x i32> [[Y]]
5858
;
5959
br i1 %cond, label %A, label %B

llvm/test/Transforms/InstCombine/freeze.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ define void @or_select_multipleuses_logical(i32 %x, i1 %y) {
9090

9191
define <3 x i4> @partial_undef_vec() {
9292
; CHECK-LABEL: @partial_undef_vec(
93-
; CHECK-NEXT: ret <3 x i4> <i4 0, i4 1, i4 0>
93+
; CHECK-NEXT: ret <3 x i4> splat (i4 1)
9494
;
9595
%f = freeze <3 x i4> <i4 poison, i4 1, i4 undef>
9696
ret <3 x i4> %f

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,8 +2652,7 @@ define <2 x i8> @partial_cond_freeze_constant_true_val_vec(<2 x i8> %x) {
26522652

26532653
define <2 x i8> @partial_cond_freeze_constant_false_val_vec(<2 x i8> %x) {
26542654
; CHECK-LABEL: @partial_cond_freeze_constant_false_val_vec(
2655-
; CHECK-NEXT: [[S1:%.*]] = insertelement <2 x i8> [[X:%.*]], i8 2, i64 1
2656-
; CHECK-NEXT: ret <2 x i8> [[S1]]
2655+
; CHECK-NEXT: ret <2 x i8> [[X:%.*]]
26572656
;
26582657
%cond.fr = freeze <2 x i1> <i1 true, i1 undef>
26592658
%s = select <2 x i1> %cond.fr, <2 x i8> %x, <2 x i8> <i8 1, i8 2>
@@ -2662,7 +2661,7 @@ define <2 x i8> @partial_cond_freeze_constant_false_val_vec(<2 x i8> %x) {
26622661

26632662
define <2 x i8> @partial_cond_freeze_both_arms_constant_vec() {
26642663
; CHECK-LABEL: @partial_cond_freeze_both_arms_constant_vec(
2665-
; CHECK-NEXT: ret <2 x i8> <i8 42, i8 2>
2664+
; CHECK-NEXT: ret <2 x i8> <i8 42, i8 43>
26662665
;
26672666
%cond.fr = freeze <2 x i1> <i1 false, i1 undef>
26682667
%s = select <2 x i1> %cond.fr, <2 x i8> <i8 1, i8 2>, <2 x i8> <i8 42, i8 43>
@@ -4904,8 +4903,7 @@ define i32 @src_simplify_2x_at_once_and(i32 %x, i32 %y) {
49044903

49054904
define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt, i1 %cond) {
49064905
; CHECK-LABEL: @select_freeze_poison_parameter(
4907-
; CHECK-NEXT: [[ADDR_SRC:%.*]] = select i1 [[COND:%.*]], ptr [[ADDR_SRC1:%.*]], ptr null
4908-
; CHECK-NEXT: store ptr [[ADDR_SRC]], ptr [[ADDR_TGT:%.*]], align 8
4906+
; CHECK-NEXT: store ptr [[ADDR_SRC:%.*]], ptr [[ADDR_TGT:%.*]], align 8
49094907
; CHECK-NEXT: ret void
49104908
;
49114909
%freeze = freeze ptr poison
@@ -4914,12 +4912,47 @@ define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt
49144912
ret void
49154913
}
49164914

4915+
define i8 @select_freeze_poison_different_parameters(i8 noundef %x, i8 noundef %y, i1 %cond1, i1 %cond2) {
4916+
; CHECK-LABEL: @select_freeze_poison_different_parameters(
4917+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i8 [[X:%.*]], i8 0
4918+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i8 [[Y:%.*]], i8 0
4919+
; CHECK-NEXT: [[CONJ:%.*]] = and i8 [[SEL1]], [[SEL2]]
4920+
; CHECK-NEXT: ret i8 [[CONJ]]
4921+
;
4922+
%freeze = freeze i8 poison
4923+
%sel1 = select i1 %cond1, i8 %x, i8 %freeze
4924+
%sel2 = select i1 %cond2, i8 %y, i8 %freeze
4925+
%conj = and i8 %sel1, %sel2
4926+
ret i8 %conj
4927+
}
4928+
4929+
define i8 @select_or_freeze_poison_parameter(i8 noundef %x, i1 %cond1) {
4930+
; CHECK-LABEL: @select_or_freeze_poison_parameter(
4931+
; CHECK-NEXT: ret i8 -1
4932+
;
4933+
%freeze = freeze i8 poison
4934+
%sel1 = select i1 %cond1, i8 -1, i8 %freeze
4935+
%or1 = or i8 %x, %freeze
4936+
%conj = and i8 %sel1, %or1
4937+
ret i8 %conj
4938+
}
4939+
4940+
define i8 @selects_freeze_poison_parameter(i8 noundef %x, i1 %cond1, i1 %cond2) {
4941+
; CHECK-LABEL: @selects_freeze_poison_parameter(
4942+
; CHECK-NEXT: ret i8 [[X:%.*]]
4943+
;
4944+
%freeze = freeze i8 poison
4945+
%sel1 = select i1 %cond1, i8 %x, i8 %freeze
4946+
%sel2 = select i1 %cond2, i8 %x, i8 %freeze
4947+
%conj = and i8 %sel1, %sel2
4948+
ret i8 %conj
4949+
}
4950+
49174951
@glb = global ptr null
49184952

49194953
define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
49204954
; CHECK-LABEL: @select_freeze_poison_global(
4921-
; CHECK-NEXT: [[SELECT_ADDR:%.*]] = select i1 [[COND:%.*]], ptr @glb, ptr null
4922-
; CHECK-NEXT: store ptr [[SELECT_ADDR]], ptr [[ADDR_TGT:%.*]], align 8
4955+
; CHECK-NEXT: store ptr @glb, ptr [[ADDR_TGT:%.*]], align 8
49234956
; CHECK-NEXT: ret void
49244957
;
49254958
%freeze = freeze ptr poison
@@ -4930,12 +4963,64 @@ define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
49304963

49314964
define void @select_freeze_poison_constant(ptr %addr.tgt, i1 %cond) {
49324965
; CHECK-LABEL: @select_freeze_poison_constant(
4933-
; CHECK-NEXT: [[SELECT_ADDR:%.*]] = select i1 [[COND:%.*]], i32 72, i32 0
4934-
; CHECK-NEXT: store i32 [[SELECT_ADDR]], ptr [[ADDR_TGT:%.*]], align 4
4966+
; CHECK-NEXT: store i32 72, ptr [[ADDR_TGT:%.*]], align 4
49354967
; CHECK-NEXT: ret void
49364968
;
49374969
%freeze = freeze i32 poison
49384970
%select.addr = select i1 %cond, i32 72, i32 %freeze
49394971
store i32 %select.addr, ptr %addr.tgt
49404972
ret void
49414973
}
4974+
4975+
define <2 x i8> @select_freeze_poison_mask_vector(i1 %cond, <2 x i8> noundef %y) {
4976+
; CHECK-LABEL: @select_freeze_poison_mask_vector(
4977+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> zeroinitializer
4978+
; CHECK-NEXT: ret <2 x i8> [[SEL]]
4979+
;
4980+
%freeze = freeze <2 x i8> <i8 0, i8 poison>
4981+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
4982+
ret <2 x i8> %sel
4983+
}
4984+
4985+
define <2 x i8> @selects_freeze_poison_mask_vector(<2 x i8> noundef %x, i1 %cond1, i1 %cond2) {
4986+
; CHECK-LABEL: @selects_freeze_poison_mask_vector(
4987+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND1:%.*]], i1 [[COND2:%.*]], i1 false
4988+
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], <2 x i8> [[X1:%.*]], <2 x i8> zeroinitializer
4989+
; CHECK-NEXT: ret <2 x i8> [[X]]
4990+
;
4991+
%freeze = freeze <2 x i8> <i8 0, i8 poison>
4992+
%sel1 = select i1 %cond1, <2 x i8> %x, <2 x i8> %freeze
4993+
%sel2 = select i1 %cond2, <2 x i8> %x, <2 x i8> %freeze
4994+
%conj = and <2 x i8> %sel1, %sel2
4995+
ret <2 x i8> %conj
4996+
}
4997+
4998+
define <2 x i8> @select_freeze_poison_splat_vector(i1 %cond, <2 x i8> noundef %y) {
4999+
; CHECK-LABEL: @select_freeze_poison_splat_vector(
5000+
; CHECK-NEXT: ret <2 x i8> [[Y:%.*]]
5001+
;
5002+
%freeze = freeze <2 x i8> <i8 poison, i8 poison>
5003+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
5004+
ret <2 x i8> %sel
5005+
}
5006+
5007+
define <2 x i8> @selects_freeze_poison_splat_vector(<2 x i8> noundef %x, i1 %cond1, i1 %cond2) {
5008+
; CHECK-LABEL: @selects_freeze_poison_splat_vector(
5009+
; CHECK-NEXT: ret <2 x i8> [[X:%.*]]
5010+
;
5011+
%freeze = freeze <2 x i8> <i8 poison, i8 poison>
5012+
%sel1 = select i1 %cond1, <2 x i8> %x, <2 x i8> %freeze
5013+
%sel2 = select i1 %cond2, <2 x i8> %x, <2 x i8> %freeze
5014+
%conj = and <2 x i8> %sel1, %sel2
5015+
ret <2 x i8> %conj
5016+
}
5017+
5018+
define <2 x i8> @select_freeze_constant_vector(i1 %cond, <2 x i8> noundef %y) {
5019+
; CHECK-LABEL: @select_freeze_constant_vector(
5020+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> zeroinitializer
5021+
; CHECK-NEXT: ret <2 x i8> [[SEL]]
5022+
;
5023+
%freeze = freeze <2 x i8> <i8 0, i8 0>
5024+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
5025+
ret <2 x i8> %sel
5026+
}

0 commit comments

Comments
 (0)