[llvm] 3c6b5d3 - [InstCombine] narrow select with FP casts

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 5 08:25:29 PST 2019


Author: Sanjay Patel
Date: 2019-12-05T11:12:44-05:00
New Revision: 3c6b5d3674e85f2be81e74d104055269c017a430

URL: https://github.com/llvm/llvm-project/commit/3c6b5d3674e85f2be81e74d104055269c017a430
DIFF: https://github.com/llvm/llvm-project/commit/3c6b5d3674e85f2be81e74d104055269c017a430.diff

LOG: [InstCombine] narrow select with FP casts

Select doesn't change values, so truncate of extended operand cancels out.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/test/Transforms/InstCombine/fptrunc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 53bcaeb98b42..8d8b2f9f8714 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1636,6 +1636,24 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &FPT) {
         return BinaryOperator::CreateFNegFMF(InnerTrunc, Op);
       return UnaryOperator::CreateFNegFMF(InnerTrunc, Op);
     }
+
+    // If we are truncating a select that has an extended operand, we can
+    // narrow the other operand and do the select as a narrow op.
+    Value *Cond, *X, *Y;
+    if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X)), m_Value(Y))) &&
+        X->getType() == Ty) {
+      // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y)
+      Value *NarrowY = Builder.CreateFPTrunc(Y, Ty);
+      Value *Sel = Builder.CreateSelect(Cond, X, NarrowY, "narrow.sel", Op);
+      return replaceInstUsesWith(FPT, Sel);
+    }
+    if (match(Op, m_Select(m_Value(Cond), m_Value(Y), m_FPExt(m_Value(X)))) &&
+        X->getType() == Ty) {
+      // fptrunc (select Cond, Y, (fpext X) --> select Cond, (fptrunc Y), X
+      Value *NarrowY = Builder.CreateFPTrunc(Y, Ty);
+      Value *Sel = Builder.CreateSelect(Cond, NarrowY, X, "narrow.sel", Op);
+      return replaceInstUsesWith(FPT, Sel);
+    }
   }
 
   if (auto *II = dyn_cast<IntrinsicInst>(FPT.getOperand(0))) {

diff  --git a/llvm/test/Transforms/InstCombine/fptrunc.ll b/llvm/test/Transforms/InstCombine/fptrunc.ll
index e1b2b1b9c531..e8038f4b8460 100644
--- a/llvm/test/Transforms/InstCombine/fptrunc.ll
+++ b/llvm/test/Transforms/InstCombine/fptrunc.ll
@@ -51,10 +51,9 @@ define <2 x half> @fmul_constant_op1(<2 x float> %x) {
 
 define float @fptrunc_select_true_val(float %x, double %y, i1 %cond) {
 ; CHECK-LABEL: @fptrunc_select_true_val(
-; CHECK-NEXT:    [[E:%.*]] = fpext float [[X:%.*]] to double
-; CHECK-NEXT:    [[SEL:%.*]] = select fast i1 [[COND:%.*]], double [[Y:%.*]], double [[E]]
-; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[SEL]] to float
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc double [[Y:%.*]] to float
+; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select fast i1 [[COND:%.*]], float [[TMP1]], float [[X:%.*]]
+; CHECK-NEXT:    ret float [[NARROW_SEL]]
 ;
   %e = fpext float %x to double
   %sel = select fast i1 %cond, double %y, double %e
@@ -64,10 +63,9 @@ define float @fptrunc_select_true_val(float %x, double %y, i1 %cond) {
 
 define <2 x float> @fptrunc_select_false_val(<2 x float> %x, <2 x double> %y, <2 x i1> %cond) {
 ; CHECK-LABEL: @fptrunc_select_false_val(
-; CHECK-NEXT:    [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
-; CHECK-NEXT:    [[SEL:%.*]] = select nnan <2 x i1> [[COND:%.*]], <2 x double> [[E]], <2 x double> [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fptrunc <2 x double> [[SEL]] to <2 x float>
-; CHECK-NEXT:    ret <2 x float> [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[Y:%.*]] to <2 x float>
+; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select nnan <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[TMP1]]
+; CHECK-NEXT:    ret <2 x float> [[NARROW_SEL]]
 ;
   %e = fpext <2 x float> %x to <2 x double>
   %sel = select nnan <2 x i1> %cond, <2 x double> %e, <2 x double> %y
@@ -81,9 +79,9 @@ define half @fptrunc_select_true_val_extra_use(half %x, float %y, i1 %cond) {
 ; CHECK-LABEL: @fptrunc_select_true_val_extra_use(
 ; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
 ; CHECK-NEXT:    call void @use(float [[E]])
-; CHECK-NEXT:    [[SEL:%.*]] = select ninf i1 [[COND:%.*]], float [[Y:%.*]], float [[E]]
-; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[SEL]] to half
-; CHECK-NEXT:    ret half [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[Y:%.*]] to half
+; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select ninf i1 [[COND:%.*]], half [[TMP1]], half [[X]]
+; CHECK-NEXT:    ret half [[NARROW_SEL]]
 ;
   %e = fpext half %x to float
   call void @use(float %e)
@@ -92,6 +90,8 @@ define half @fptrunc_select_true_val_extra_use(half %x, float %y, i1 %cond) {
   ret half %r
 }
 
+; Negative test - this would require an extra instruction.
+
 define half @fptrunc_select_true_val_extra_use_2(half %x, float %y, i1 %cond) {
 ; CHECK-LABEL: @fptrunc_select_true_val_extra_use_2(
 ; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
@@ -107,6 +107,8 @@ define half @fptrunc_select_true_val_extra_use_2(half %x, float %y, i1 %cond) {
   ret half %r
 }
 
+; Negative test - the extend must be from the same source type as the result of the trunc.
+
 define float @fptrunc_select_true_val_type_mismatch(half %x, double %y, i1 %cond) {
 ; CHECK-LABEL: @fptrunc_select_true_val_type_mismatch(
 ; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
@@ -120,6 +122,8 @@ define float @fptrunc_select_true_val_type_mismatch(half %x, double %y, i1 %cond
   ret float %r
 }
 
+; Negative test - but given enough FMF, should this be folded?
+
 define float @fptrunc_select_true_val_type_mismatch_fast(half %x, double %y, i1 %cond) {
 ; CHECK-LABEL: @fptrunc_select_true_val_type_mismatch_fast(
 ; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double


        


More information about the llvm-commits mailing list