Skip to content

Commit cd63f3a

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
1 parent 397696b commit cd63f3a

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4812,7 +4812,7 @@ 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) {
4815+
auto getConstantReplacement = [&I](Type *Ty) {
48164816
Constant *BestValue = nullptr;
48174817
Constant *NullValue = Constant::getNullValue(Ty);
48184818
for (const auto *U : I.users()) {
@@ -4831,18 +4831,38 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
48314831
return BestValue;
48324832
};
48334833

4834+
auto getValueReplacement = [&I, &AC = this->AC, &DT = this->DT]() -> Value * {
4835+
Value *BestValue = nullptr;
4836+
for (const auto *U : I.users()) {
4837+
Value *C = nullptr;
4838+
Value *SelectArgument = nullptr;
4839+
if (match(U, m_c_Select(m_Specific(&I), m_Value(SelectArgument))) &&
4840+
isGuaranteedNotToBeUndefOrPoison(SelectArgument, &AC, &I, &DT))
4841+
C = SelectArgument;
4842+
4843+
if (!BestValue)
4844+
BestValue = C;
4845+
else if (BestValue != C)
4846+
return nullptr;
4847+
}
4848+
return BestValue;
4849+
};
4850+
48344851
if (match(Op0, m_Undef())) {
48354852
// Don't fold freeze(undef/poison) if it's used as a vector operand in
48364853
// a shuffle. This may improve codegen for shuffles that allow
48374854
// unspecified inputs.
48384855
if (isUsedWithinShuffleVector(&I))
48394856
return nullptr;
4840-
return replaceInstUsesWith(I, getUndefReplacement(I.getType()));
4857+
if (auto *Replace = getValueReplacement())
4858+
return replaceInstUsesWith(I, Replace);
4859+
else
4860+
return replaceInstUsesWith(I, getConstantReplacement(I.getType()));
48414861
}
48424862

48434863
Constant *C;
48444864
if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement()) {
4845-
Constant *ReplaceC = getUndefReplacement(I.getType()->getScalarType());
4865+
Constant *ReplaceC = getConstantReplacement(I.getType()->getScalarType());
48464866
return replaceInstUsesWith(I, Constant::replaceUndefsWith(C, ReplaceC));
48474867
}
48484868

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4904,8 +4904,7 @@ define i32 @src_simplify_2x_at_once_and(i32 %x, i32 %y) {
49044904

49054905
define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt, i1 %cond) {
49064906
; 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
4907+
; CHECK-NEXT: store ptr [[ADDR_SRC:%.*]], ptr [[ADDR_TGT:%.*]], align 8
49094908
; CHECK-NEXT: ret void
49104909
;
49114910
%freeze = freeze ptr poison
@@ -4914,12 +4913,36 @@ define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt
49144913
ret void
49154914
}
49164915

4916+
define i8 @select_freeze_poison_different_parameters(i8 noundef %x, i8 noundef %y, i1 %cond1, i1 %cond2) {
4917+
; CHECK-LABEL: @select_freeze_poison_different_parameters(
4918+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i8 [[X:%.*]], i8 0
4919+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i8 [[Y:%.*]], i8 0
4920+
; CHECK-NEXT: [[CONJ:%.*]] = and i8 [[SEL1]], [[SEL2]]
4921+
; CHECK-NEXT: ret i8 [[CONJ]]
4922+
;
4923+
%freeze = freeze i8 poison
4924+
%sel1 = select i1 %cond1, i8 %x, i8 %freeze
4925+
%sel2 = select i1 %cond2, i8 %y, i8 %freeze
4926+
%conj = and i8 %sel1, %sel2
4927+
ret i8 %conj
4928+
}
4929+
4930+
define i8 @selects_freeze_poison_parameter(i8 noundef %x, i1 %cond1, i1 %cond2) {
4931+
; CHECK-LABEL: @selects_freeze_poison_parameter(
4932+
; CHECK-NEXT: ret i8 [[X:%.*]]
4933+
;
4934+
%freeze = freeze i8 poison
4935+
%sel1 = select i1 %cond1, i8 %x, i8 %freeze
4936+
%sel2 = select i1 %cond2, i8 %x, i8 %freeze
4937+
%conj = and i8 %sel1, %sel2
4938+
ret i8 %conj
4939+
}
4940+
49174941
@glb = global ptr null
49184942

49194943
define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
49204944
; 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
4945+
; CHECK-NEXT: store ptr @glb, ptr [[ADDR_TGT:%.*]], align 8
49234946
; CHECK-NEXT: ret void
49244947
;
49254948
%freeze = freeze ptr poison
@@ -4930,12 +4953,64 @@ define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
49304953

49314954
define void @select_freeze_poison_constant(ptr %addr.tgt, i1 %cond) {
49324955
; 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
4956+
; CHECK-NEXT: store i32 72, ptr [[ADDR_TGT:%.*]], align 4
49354957
; CHECK-NEXT: ret void
49364958
;
49374959
%freeze = freeze i32 poison
49384960
%select.addr = select i1 %cond, i32 72, i32 %freeze
49394961
store i32 %select.addr, ptr %addr.tgt
49404962
ret void
49414963
}
4964+
4965+
define <2 x i8> @select_freeze_poison_mask_vector(i1 %cond, <2 x i8> noundef %y) {
4966+
; CHECK-LABEL: @select_freeze_poison_mask_vector(
4967+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> zeroinitializer
4968+
; CHECK-NEXT: ret <2 x i8> [[SEL]]
4969+
;
4970+
%freeze = freeze <2 x i8> <i8 0, i8 poison>
4971+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
4972+
ret <2 x i8> %sel
4973+
}
4974+
4975+
define <2 x i8> @selects_freeze_poison_mask_vector(<2 x i8> noundef %x, i1 %cond1, i1 %cond2) {
4976+
; CHECK-LABEL: @selects_freeze_poison_mask_vector(
4977+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND1:%.*]], i1 [[COND2:%.*]], i1 false
4978+
; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP1]], <2 x i8> [[X1:%.*]], <2 x i8> zeroinitializer
4979+
; CHECK-NEXT: ret <2 x i8> [[X]]
4980+
;
4981+
%freeze = freeze <2 x i8> <i8 0, i8 poison>
4982+
%sel1 = select i1 %cond1, <2 x i8> %x, <2 x i8> %freeze
4983+
%sel2 = select i1 %cond2, <2 x i8> %x, <2 x i8> %freeze
4984+
%conj = and <2 x i8> %sel1, %sel2
4985+
ret <2 x i8> %conj
4986+
}
4987+
4988+
define <2 x i8> @select_freeze_poison_splat_vector(i1 %cond, <2 x i8> noundef %y) {
4989+
; CHECK-LABEL: @select_freeze_poison_splat_vector(
4990+
; CHECK-NEXT: ret <2 x i8> [[Y:%.*]]
4991+
;
4992+
%freeze = freeze <2 x i8> <i8 poison, i8 poison>
4993+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
4994+
ret <2 x i8> %sel
4995+
}
4996+
4997+
define <2 x i8> @selects_freeze_poison_splat_vector(<2 x i8> noundef %x, i1 %cond1, i1 %cond2) {
4998+
; CHECK-LABEL: @selects_freeze_poison_splat_vector(
4999+
; CHECK-NEXT: ret <2 x i8> [[X:%.*]]
5000+
;
5001+
%freeze = freeze <2 x i8> <i8 poison, i8 poison>
5002+
%sel1 = select i1 %cond1, <2 x i8> %x, <2 x i8> %freeze
5003+
%sel2 = select i1 %cond2, <2 x i8> %x, <2 x i8> %freeze
5004+
%conj = and <2 x i8> %sel1, %sel2
5005+
ret <2 x i8> %conj
5006+
}
5007+
5008+
define <2 x i8> @select_freeze_constant_vector(i1 %cond, <2 x i8> noundef %y) {
5009+
; CHECK-LABEL: @select_freeze_constant_vector(
5010+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> zeroinitializer
5011+
; CHECK-NEXT: ret <2 x i8> [[SEL]]
5012+
;
5013+
%freeze = freeze <2 x i8> <i8 0, i8 0>
5014+
%sel = select i1 %cond, <2 x i8> %y, <2 x i8> %freeze
5015+
ret <2 x i8> %sel
5016+
}

0 commit comments

Comments
 (0)