[llvm] r346169 - [InstSimplify] fold select (fcmp X, Y), X, Y
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 5 13:51:39 PST 2018
Author: spatel
Date: Mon Nov 5 13:51:39 2018
New Revision: 346169
URL: http://llvm.org/viewvc/llvm-project?rev=346169&view=rev
Log:
[InstSimplify] fold select (fcmp X, Y), X, Y
This is NFCI for InstCombine because it calls InstSimplify,
so I left the tests for this transform there. As noted in
the code comment, we can allow this fold more often by using
FMF and/or value tracking.
Modified:
llvm/trunk/lib/Analysis/InstructionSimplify.cpp
llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll
Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Mon Nov 5 13:51:39 2018
@@ -3874,6 +3874,34 @@ static Value *simplifySelectWithICmpCond
return nullptr;
}
+/// Try to simplify a select instruction when its condition operand is a
+/// floating-point comparison.
+static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F) {
+ FCmpInst::Predicate Pred;
+ if (!match(Cond, m_FCmp(Pred, m_Specific(T), m_Specific(F))) &&
+ !match(Cond, m_FCmp(Pred, m_Specific(F), m_Specific(T))))
+ return nullptr;
+
+ // TODO: The transform may not be valid with -0.0. An incomplete way of
+ // testing for that possibility is to check if at least one operand is a
+ // non-zero constant.
+ const APFloat *C;
+ if ((match(T, m_APFloat(C)) && C->isNonZero()) ||
+ (match(F, m_APFloat(C)) && C->isNonZero())) {
+ // (T == F) ? T : F --> F
+ // (F == T) ? T : F --> F
+ if (Pred == FCmpInst::FCMP_OEQ)
+ return F;
+
+ // (T != F) ? T : F --> T
+ // (F != T) ? T : F --> T
+ if (Pred == FCmpInst::FCMP_UNE)
+ return T;
+ }
+
+ return nullptr;
+}
+
/// Given operands for a SelectInst, see if we can fold the result.
/// If not, this returns null.
static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
@@ -3910,6 +3938,9 @@ static Value *SimplifySelectInst(Value *
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
return V;
+ if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal))
+ return V;
+
if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
return V;
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Mon Nov 5 13:51:39 2018
@@ -1660,31 +1660,6 @@ Instruction *InstCombiner::visitSelectIn
// See if we are selecting two values based on a comparison of the two values.
if (FCmpInst *FCI = dyn_cast<FCmpInst>(CondVal)) {
if (FCI->getOperand(0) == TrueVal && FCI->getOperand(1) == FalseVal) {
- // Transform (X == Y) ? X : Y -> Y
- if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) {
- // This is not safe in general for floating point:
- // consider X== -0, Y== +0.
- // It becomes safe if either operand is a nonzero constant.
- ConstantFP *CFPt, *CFPf;
- if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
- !CFPt->getValueAPF().isZero()) ||
- ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
- !CFPf->getValueAPF().isZero()))
- return replaceInstUsesWith(SI, FalseVal);
- }
- // Transform (X une Y) ? X : Y -> X
- if (FCI->getPredicate() == FCmpInst::FCMP_UNE) {
- // This is not safe in general for floating point:
- // consider X== -0, Y== +0.
- // It becomes safe if either operand is a nonzero constant.
- ConstantFP *CFPt, *CFPf;
- if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
- !CFPt->getValueAPF().isZero()) ||
- ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
- !CFPf->getValueAPF().isZero()))
- return replaceInstUsesWith(SI, TrueVal);
- }
-
// Canonicalize to use ordered comparisons by swapping the select
// operands.
//
@@ -1703,31 +1678,6 @@ Instruction *InstCombiner::visitSelectIn
// NOTE: if we wanted to, this is where to detect MIN/MAX
} else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){
- // Transform (X == Y) ? Y : X -> X
- if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) {
- // This is not safe in general for floating point:
- // consider X== -0, Y== +0.
- // It becomes safe if either operand is a nonzero constant.
- ConstantFP *CFPt, *CFPf;
- if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
- !CFPt->getValueAPF().isZero()) ||
- ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
- !CFPf->getValueAPF().isZero()))
- return replaceInstUsesWith(SI, FalseVal);
- }
- // Transform (X une Y) ? Y : X -> Y
- if (FCI->getPredicate() == FCmpInst::FCMP_UNE) {
- // This is not safe in general for floating point:
- // consider X== -0, Y== +0.
- // It becomes safe if either operand is a nonzero constant.
- ConstantFP *CFPt, *CFPf;
- if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) &&
- !CFPt->getValueAPF().isZero()) ||
- ((CFPf = dyn_cast<ConstantFP>(FalseVal)) &&
- !CFPf->getValueAPF().isZero()))
- return replaceInstUsesWith(SI, TrueVal);
- }
-
// Canonicalize to use ordered comparisons by swapping the select
// operands.
//
Modified: llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll?rev=346169&r1=346168&r2=346169&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/fcmp-select.ll Mon Nov 5 13:51:39 2018
@@ -5,9 +5,7 @@
define double @oeq(double %x) {
; CHECK-LABEL: @oeq(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
-; CHECK-NEXT: ret double [[COND]]
+; CHECK-NEXT: ret double 4.200000e+01
;
%cmp = fcmp oeq double %x, 42.0
%cond = select i1 %cmp, double %x, double 42.0
@@ -18,9 +16,7 @@ define double @oeq(double %x) {
define float @oeq_swapped(float %x) {
; CHECK-LABEL: @oeq_swapped(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X:%.*]], 4.200000e+01
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], float 4.200000e+01, float [[X]]
-; CHECK-NEXT: ret float [[COND]]
+; CHECK-NEXT: ret float [[X:%.*]]
;
%cmp = fcmp oeq float %x, 42.0
%cond = select i1 %cmp, float 42.0, float %x
@@ -34,9 +30,7 @@ define float @oeq_swapped(float %x) {
define double @une(double %x) {
; CHECK-LABEL: @une(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
-; CHECK-NEXT: ret double [[COND]]
+; CHECK-NEXT: ret double [[X:%.*]]
;
%cmp = fcmp une double %x, 42.0
%cond = select i1 %cmp, double %x, double 42.0
@@ -47,9 +41,7 @@ define double @une(double %x) {
define double @une_swapped(double %x) {
; CHECK-LABEL: @une_swapped(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double 4.200000e+01, double [[X]]
-; CHECK-NEXT: ret double [[COND]]
+; CHECK-NEXT: ret double 4.200000e+01
;
%cmp = fcmp une double %x, 42.0
%cond = select i1 %cmp, double 42.0, double %x
More information about the llvm-commits
mailing list