Skip to content

Commit 72f543c

Browse files
committed
InstSimplify: support floating-point equivalences
Since cd16b07 (IR: introduce CmpInst::isEquivalence), there is now an isEquivalence routine in CmpInst that we can use to determine equivalence in simplifySelectWithICmpEq. Implement this, extending the code from integer-equalities to integer and floating-point equivalences.
1 parent 455ef03 commit 72f543c

File tree

2 files changed

+74
-91
lines changed

2 files changed

+74
-91
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4466,13 +4466,15 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
44664466
} else
44674467
return nullptr;
44684468
}
4469-
Constant *Res = ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI);
4469+
Constant *Res = ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI,
4470+
/*AllowNonDeterministic=*/false);
44704471
if (DropFlags && Res && I->hasPoisonGeneratingAnnotations())
44714472
DropFlags->push_back(I);
44724473
return Res;
44734474
}
44744475

4475-
return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI);
4476+
return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI,
4477+
/*AllowNonDeterministic=*/false);
44764478
}
44774479

44784480
Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
@@ -4616,11 +4618,11 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
46164618
}
46174619

46184620
/// Try to simplify a select instruction when its condition operand is an
4619-
/// integer equality comparison.
4620-
static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
4621-
Value *TrueVal, Value *FalseVal,
4622-
const SimplifyQuery &Q,
4623-
unsigned MaxRecurse) {
4621+
/// integer equality or floating-point equivalence comparison.
4622+
static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS,
4623+
Value *TrueVal, Value *FalseVal,
4624+
const SimplifyQuery &Q,
4625+
unsigned MaxRecurse) {
46244626
if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
46254627
/* AllowRefinement */ false,
46264628
/* DropFlags */ nullptr, MaxRecurse) == TrueVal)
@@ -4721,11 +4723,11 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47214723
// the arms of the select. See if substituting this value into the arm and
47224724
// simplifying the result yields the same value as the other arm.
47234725
if (Pred == ICmpInst::ICMP_EQ) {
4724-
if (Value *V = simplifySelectWithICmpEq(CmpLHS, CmpRHS, TrueVal, FalseVal,
4725-
Q, MaxRecurse))
4726+
if (Value *V = simplifySelectWithEquivalence(CmpLHS, CmpRHS, TrueVal,
4727+
FalseVal, Q, MaxRecurse))
47264728
return V;
4727-
if (Value *V = simplifySelectWithICmpEq(CmpRHS, CmpLHS, TrueVal, FalseVal,
4728-
Q, MaxRecurse))
4729+
if (Value *V = simplifySelectWithEquivalence(CmpRHS, CmpLHS, TrueVal,
4730+
FalseVal, Q, MaxRecurse))
47294731
return V;
47304732

47314733
Value *X;
@@ -4734,23 +4736,23 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47344736
if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
47354737
match(CmpRHS, m_Zero())) {
47364738
// (X | Y) == 0 implies X == 0 and Y == 0.
4737-
if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
4738-
MaxRecurse))
4739+
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4740+
Q, MaxRecurse))
47394741
return V;
4740-
if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
4741-
MaxRecurse))
4742+
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4743+
Q, MaxRecurse))
47424744
return V;
47434745
}
47444746

47454747
// select((X & Y) == -1 ? X : -1) --> -1 (commuted 2 ways)
47464748
if (match(CmpLHS, m_And(m_Value(X), m_Value(Y))) &&
47474749
match(CmpRHS, m_AllOnes())) {
47484750
// (X & Y) == -1 implies X == -1 and Y == -1.
4749-
if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
4750-
MaxRecurse))
4751+
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4752+
Q, MaxRecurse))
47514753
return V;
4752-
if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
4753-
MaxRecurse))
4754+
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4755+
Q, MaxRecurse))
47544756
return V;
47554757
}
47564758
}
@@ -4761,27 +4763,51 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47614763
/// Try to simplify a select instruction when its condition operand is a
47624764
/// floating-point comparison.
47634765
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
4764-
const SimplifyQuery &Q) {
4766+
const SimplifyQuery &Q,
4767+
unsigned MaxRecurse) {
47654768
FCmpInst::Predicate Pred;
4766-
if (!match(Cond, m_FCmp(Pred, m_Specific(T), m_Specific(F))) &&
4767-
!match(Cond, m_FCmp(Pred, m_Specific(F), m_Specific(T))))
4769+
Value *CmpLHS, *CmpRHS;
4770+
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
4771+
return nullptr;
4772+
FCmpInst *I = cast<FCmpInst>(Cond);
4773+
4774+
bool IsEquiv = I->isEquivalence(),
4775+
IsInverseEquiv = I->isEquivalence(/*Invert=*/true);
4776+
4777+
if (IsInverseEquiv)
4778+
std::swap(T, F);
4779+
4780+
// Canonicalize CmpLHS to be T, and CmpRHS to be F, if they're swapped.
4781+
if (CmpLHS == F && CmpRHS == T)
4782+
std::swap(CmpLHS, CmpRHS);
4783+
4784+
// This transforms is safe if at least one operand is known to not be zero.
4785+
// Otherwise, the select can change the sign of a zero operand.
4786+
if (IsEquiv || IsInverseEquiv) {
4787+
if (Value *V =
4788+
simplifySelectWithEquivalence(CmpLHS, CmpRHS, T, F, Q, MaxRecurse))
4789+
return V;
4790+
if (Value *V =
4791+
simplifySelectWithEquivalence(CmpRHS, CmpLHS, T, F, Q, MaxRecurse))
4792+
return V;
4793+
4794+
// (T == F) ? T : F --> F
4795+
// (T != F) ? F : T --> F
4796+
return CmpLHS == T && CmpRHS == F ? F : nullptr;
4797+
}
4798+
4799+
if (CmpLHS != T || CmpRHS != F)
47684800
return nullptr;
47694801

4770-
// This transform is safe if we do not have (do not care about) -0.0 or if
4771-
// at least one operand is known to not be -0.0. Otherwise, the select can
4772-
// change the sign of a zero operand.
4802+
// This transform is also safe if we do not have (do not care about) -0.0.
47734803
bool HasNoSignedZeros =
47744804
Q.CxtI && isa<FPMathOperator>(Q.CxtI) && Q.CxtI->hasNoSignedZeros();
4775-
const APFloat *C;
4776-
if (HasNoSignedZeros || (match(T, m_APFloat(C)) && C->isNonZero()) ||
4777-
(match(F, m_APFloat(C)) && C->isNonZero())) {
4805+
if (HasNoSignedZeros) {
47784806
// (T == F) ? T : F --> F
4779-
// (F == T) ? T : F --> F
47804807
if (Pred == FCmpInst::FCMP_OEQ)
47814808
return F;
47824809

47834810
// (T != F) ? T : F --> T
4784-
// (F != T) ? T : F --> T
47854811
if (Pred == FCmpInst::FCMP_UNE)
47864812
return T;
47874813
}
@@ -4955,7 +4981,7 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
49554981
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
49564982
return V;
49574983

4958-
if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal, Q))
4984+
if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal, Q, MaxRecurse))
49594985
return V;
49604986

49614987
if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))

llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll

Lines changed: 17 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33

44
define float @select_fcmp_fsub_oeq(float %x) {
55
; CHECK-LABEL: @select_fcmp_fsub_oeq(
6-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 2.000000e+00
7-
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
8-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
9-
; CHECK-NEXT: ret float [[SEL]]
6+
; CHECK-NEXT: ret float 0.000000e+00
107
;
118
%fcmp = fcmp oeq float %x, 2.0
129
%fadd = fsub float %x, 2.0
@@ -42,10 +39,7 @@ define float @select_fcmp_fsub_ueq(float %x) {
4239

4340
define float @select_fcmp_fsub_ueq_nnan(float %x) {
4441
; CHECK-LABEL: @select_fcmp_fsub_ueq_nnan(
45-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan ueq float [[X:%.*]], 2.000000e+00
46-
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
47-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
48-
; CHECK-NEXT: ret float [[SEL]]
42+
; CHECK-NEXT: ret float 0.000000e+00
4943
;
5044
%fcmp = fcmp nnan ueq float %x, 2.0
5145
%fadd = fsub float %x, 2.0
@@ -55,10 +49,7 @@ define float @select_fcmp_fsub_ueq_nnan(float %x) {
5549

5650
define float @select_fcmp_fsub_une(float %x) {
5751
; CHECK-LABEL: @select_fcmp_fsub_une(
58-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp une float [[X:%.*]], 2.000000e+00
59-
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
60-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
61-
; CHECK-NEXT: ret float [[SEL]]
52+
; CHECK-NEXT: ret float 0.000000e+00
6253
;
6354
%fcmp = fcmp une float %x, 2.0
6455
%fadd = fsub float %x, 2.0
@@ -94,10 +85,7 @@ define float @select_fcmp_fsub_one(float %x) {
9485

9586
define float @select_fcmp_fsub_one_nnan(float %x) {
9687
; CHECK-LABEL: @select_fcmp_fsub_one_nnan(
97-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan one float [[X:%.*]], 2.000000e+00
98-
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
99-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
100-
; CHECK-NEXT: ret float [[SEL]]
88+
; CHECK-NEXT: ret float 0.000000e+00
10189
;
10290
%fcmp = fcmp nnan one float %x, 2.0
10391
%fadd = fsub float %x, 2.0
@@ -107,10 +95,7 @@ define float @select_fcmp_fsub_one_nnan(float %x) {
10795

10896
define float @select_fcmp_fadd(float %x) {
10997
; CHECK-LABEL: @select_fcmp_fadd(
110-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 2.000000e+00
111-
; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], 2.000000e+00
112-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 4.000000e+00
113-
; CHECK-NEXT: ret float [[SEL]]
98+
; CHECK-NEXT: ret float 4.000000e+00
11499
;
115100
%fcmp = fcmp oeq float %x, 2.0
116101
%fadd = fadd float %x, 2.0
@@ -120,10 +105,7 @@ define float @select_fcmp_fadd(float %x) {
120105

121106
define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x) {
122107
; CHECK-LABEL: @select_fcmp_fadd_vec(
123-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x float> [[X:%.*]], splat (float 2.000000e+00)
124-
; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], splat (float 2.000000e+00)
125-
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[FADD]], <2 x float> splat (float 4.000000e+00)
126-
; CHECK-NEXT: ret <2 x float> [[SEL]]
108+
; CHECK-NEXT: ret <2 x float> splat (float 4.000000e+00)
127109
;
128110
%fcmp = fcmp oeq <2 x float> %x, <float 2.0, float 2.0>
129111
%fadd = fadd <2 x float> %x, <float 2.0, float 2.0>
@@ -134,10 +116,8 @@ define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x) {
134116

135117
define float @select_fcmp_fmul_nonrefinement(float %x, float %y) {
136118
; CHECK-LABEL: @select_fcmp_fmul_nonrefinement(
137-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
138-
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X]]
139-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FMUL]]
140-
; CHECK-NEXT: ret float [[SEL]]
119+
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X:%.*]]
120+
; CHECK-NEXT: ret float [[FMUL]]
141121
;
142122
%fcmp = fcmp oeq float %x, 1.0
143123
%fmul = fmul float %y, %x
@@ -147,10 +127,7 @@ define float @select_fcmp_fmul_nonrefinement(float %x, float %y) {
147127

148128
define float @select_fcmp_fmul(float %x) {
149129
; CHECK-LABEL: @select_fcmp_fmul(
150-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 2.000000e+00
151-
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[X]], 2.000000e+00
152-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FMUL]], float 4.000000e+00
153-
; CHECK-NEXT: ret float [[SEL]]
130+
; CHECK-NEXT: ret float 4.000000e+00
154131
;
155132
%fcmp = fcmp oeq float %x, 2.0
156133
%fmul = fmul float %x, 2.0
@@ -160,10 +137,8 @@ define float @select_fcmp_fmul(float %x) {
160137

161138
define float @select_fcmp_fdiv_nonrefinement(float %x, float %y) {
162139
; CHECK-LABEL: @select_fcmp_fdiv_nonrefinement(
163-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
164-
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X]]
165-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FDIV]]
166-
; CHECK-NEXT: ret float [[SEL]]
140+
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X:%.*]]
141+
; CHECK-NEXT: ret float [[FDIV]]
167142
;
168143
%fcmp = fcmp oeq float %x, 1.0
169144
%fdiv = fdiv float %y, %x
@@ -173,10 +148,7 @@ define float @select_fcmp_fdiv_nonrefinement(float %x, float %y) {
173148

174149
define float @select_fcmp_fdiv(float %x) {
175150
; CHECK-LABEL: @select_fcmp_fdiv(
176-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 2.000000e+00
177-
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[X]], 2.000000e+00
178-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FDIV]], float 1.000000e+00
179-
; CHECK-NEXT: ret float [[SEL]]
151+
; CHECK-NEXT: ret float 1.000000e+00
180152
;
181153
%fcmp = fcmp oeq float %x, 2.0
182154
%fdiv = fdiv float %x, 2.0
@@ -186,10 +158,7 @@ define float @select_fcmp_fdiv(float %x) {
186158

187159
define float @select_fcmp_frem(float %x) {
188160
; CHECK-LABEL: @select_fcmp_frem(
189-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 3.000000e+00
190-
; CHECK-NEXT: [[FREM:%.*]] = frem float [[X]], 2.000000e+00
191-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FREM]], float 1.000000e+00
192-
; CHECK-NEXT: ret float [[SEL]]
161+
; CHECK-NEXT: ret float 1.000000e+00
193162
;
194163
%fcmp = fcmp oeq float %x, 3.0
195164
%frem = frem float %x, 2.0
@@ -199,10 +168,7 @@ define float @select_fcmp_frem(float %x) {
199168

200169
define <2 x float> @select_fcmp_insertelement(<2 x float> %x) {
201170
; CHECK-LABEL: @select_fcmp_insertelement(
202-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x float> [[X:%.*]], splat (float 2.000000e+00)
203-
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <2 x float> [[X]], float 4.000000e+00, i64 0
204-
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[INSERT]], <2 x float> <float 4.000000e+00, float 2.000000e+00>
205-
; CHECK-NEXT: ret <2 x float> [[SEL]]
171+
; CHECK-NEXT: ret <2 x float> <float 4.000000e+00, float 2.000000e+00>
206172
;
207173
%fcmp = fcmp oeq <2 x float> %x, <float 2.0, float 2.0>
208174
%insert = insertelement <2 x float> %x, float 4.0, i64 0
@@ -212,10 +178,7 @@ define <2 x float> @select_fcmp_insertelement(<2 x float> %x) {
212178

213179
define <4 x float> @select_fcmp_shufflevector_select(<4 x float> %x) {
214180
; CHECK-LABEL: @select_fcmp_shufflevector_select(
215-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <4 x float> [[X:%.*]], splat (float 2.000000e+00)
216-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
217-
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[FCMP]], <4 x float> [[SHUFFLE]], <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
218-
; CHECK-NEXT: ret <4 x float> [[SEL]]
181+
; CHECK-NEXT: ret <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
219182
;
220183
%fcmp = fcmp oeq <4 x float> %x, <float 2.0, float 2.0, float 2.0, float 2.0>
221184
%shuffle = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
@@ -240,10 +203,7 @@ define float @select_fcmp_sin_nonrefinement(float %x) {
240203
; The hexfloat constant is PI / 2.
241204
define float @select_fcmp_sin(float %x) {
242205
; CHECK-LABEL: @select_fcmp_sin(
243-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 0x3FF921FB60000000
244-
; CHECK-NEXT: [[SIN:%.*]] = call float @llvm.sin.f32(float [[X]])
245-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[SIN]], float 1.000000e+00
246-
; CHECK-NEXT: ret float [[SEL]]
206+
; CHECK-NEXT: ret float 1.000000e+00
247207
;
248208
%fcmp = fcmp oeq float %x, 0x3FF921FB60000000
249209
%sin = call float @llvm.sin.f32(float %x)
@@ -268,10 +228,7 @@ define float @select_fcmp_cos_nonrefinement(float %x) {
268228
; The hexfloat constant is PI.
269229
define float @select_fcmp_cos(float %x) {
270230
; CHECK-LABEL: @select_fcmp_cos(
271-
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 0x400921FB60000000
272-
; CHECK-NEXT: [[COS:%.*]] = call float @llvm.cos.f32(float [[X]])
273-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[COS]], float -1.000000e+00
274-
; CHECK-NEXT: ret float [[SEL]]
231+
; CHECK-NEXT: ret float -1.000000e+00
275232
;
276233
%fcmp = fcmp oeq float %x, 0x400921FB60000000
277234
%cos = call float @llvm.cos.f32(float %x)

0 commit comments

Comments
 (0)