Skip to content

Commit af0ad2f

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 5946696 commit af0ad2f

File tree

4 files changed

+153
-22
lines changed

4 files changed

+153
-22
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4812,19 +4812,23 @@ 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 = [&](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 *V = NullValue;
48204820
if (match(U, m_Or(m_Value(), m_Value())))
4821-
C = ConstantInt::getAllOnesValue(Ty);
4821+
V = ConstantInt::getAllOnesValue(Ty);
48224822
else if (match(U, m_Select(m_Specific(&I), m_Constant(), m_Value())))
4823-
C = ConstantInt::getTrue(Ty);
4823+
V = ConstantInt::getTrue(Ty);
4824+
else if (match(U, m_c_Select(m_Specific(&I), m_Value(V)))) {
4825+
if (!isGuaranteedNotToBeUndefOrPoison(V, &AC, &I, &DT))
4826+
V = NullValue;
4827+
}
48244828

48254829
if (!BestValue)
4826-
BestValue = C;
4827-
else if (BestValue != C)
4830+
BestValue = V;
4831+
else if (BestValue != V)
48284832
BestValue = NullValue;
48294833
}
48304834
assert(BestValue && "Must have at least one use");
@@ -4840,10 +4844,28 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
48404844
return replaceInstUsesWith(I, getUndefReplacement(I.getType()));
48414845
}
48424846

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

48494871
// 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: 118 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,88 @@ 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+
}
5027+
5028+
define <2 x i8> @select_freeze_constant_expression_vector_add(i1 %cond, <2 x i8> noundef %y) {
5029+
; CHECK-LABEL: @select_freeze_constant_expression_vector_add(
5030+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> splat (i8 3)
5031+
; CHECK-NEXT: ret <2 x i8> [[SEL]]
5032+
;
5033+
%freeze = freeze <2 x i8> <i8 poison, i8 add (i8 1, i8 2)>
5034+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
5035+
ret <2 x i8> %sel
5036+
}
5037+
5038+
%struct.1 = type {i32, i32}
5039+
@glb.struct.1 = global %struct.1 {i32 1, i32 2}
5040+
5041+
define <2 x ptr> @select_freeze_constant_expression_vector_gep(i1 %cond, <2 x ptr> noundef %y) {
5042+
; CHECK-LABEL: @select_freeze_constant_expression_vector_gep(
5043+
; CHECK-NEXT: [[FREEZE:%.*]] = freeze <2 x ptr> <ptr poison, ptr getelementptr inbounds nuw (i8, ptr @glb.struct.1, i64 800)>
5044+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x ptr> [[Y:%.*]], <2 x ptr> [[FREEZE]]
5045+
; CHECK-NEXT: ret <2 x ptr> [[SEL]]
5046+
;
5047+
%freeze = freeze <2 x ptr> <ptr poison, ptr getelementptr inbounds (%struct.1, ptr @glb.struct.1, i64 100)>
5048+
%sel = select i1 %cond, <2 x ptr> %y, <2 x ptr> %freeze
5049+
ret <2 x ptr> %sel
5050+
}

0 commit comments

Comments
 (0)