From 580c45b12d8a0c407428862fab8c380146ae94e0 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 27 Sep 2017 17:16:51 +0000 Subject: [PATCH] [InstCombine] Gating select arithmetic optimization. These changes faciliate positive behavior for arithmetic based select expressions that match its translation criteria, keeping code size gated to neutral or improved scenarios. Patch by Michael Berg ! Differential Revision: https://reviews.llvm.org/D38263 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314320 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstructionCombining.cpp | 5 +- .../InstCombine/select_arithmetic.ll | 48 ++++++++++++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 60db2ddb63c..2271e219d0f 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -731,6 +731,7 @@ Value *InstCombiner::SimplifySelectsFeedingBinaryOp(BinaryOperator &I, Value *SI = nullptr; if (match(LHS, m_Select(m_Value(A), m_Value(B), m_Value(C))) && match(RHS, m_Select(m_Specific(A), m_Value(D), m_Value(E)))) { + bool SelectsHaveOneUse = LHS->hasOneUse() && RHS->hasOneUse(); BuilderTy::FastMathFlagGuard Guard(Builder); if (isa(&I)) Builder.setFastMathFlags(I.getFastMathFlags()); @@ -739,9 +740,9 @@ Value *InstCombiner::SimplifySelectsFeedingBinaryOp(BinaryOperator &I, Value *V2 = SimplifyBinOp(Opcode, B, D, SQ.getWithInstruction(&I)); if (V1 && V2) SI = Builder.CreateSelect(A, V2, V1); - else if (V2) + else if (V2 && SelectsHaveOneUse) SI = Builder.CreateSelect(A, V2, Builder.CreateBinOp(Opcode, C, E)); - else if (V1) + else if (V1 && SelectsHaveOneUse) SI = Builder.CreateSelect(A, Builder.CreateBinOp(Opcode, B, D), V1); if (SI) diff --git a/test/Transforms/InstCombine/select_arithmetic.ll b/test/Transforms/InstCombine/select_arithmetic.ll index d33bbdd1d43..8fde7c0807e 100644 --- a/test/Transforms/InstCombine/select_arithmetic.ll +++ b/test/Transforms/InstCombine/select_arithmetic.ll @@ -3,17 +3,32 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; Tests folding constants from two similar selects that feed a add -define float @test1(i1 zeroext %arg) #0 { +define float @test1a(i1 zeroext %arg) #0 { %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00 %tmp1 = select i1 %arg, float 1.000000e+00, float 9.000000e+00 %tmp2 = fadd float %tmp, %tmp1 ret float %tmp2 -; CHECK-LABEL: @test1( +; CHECK-LABEL: @test1a( ; CHECK: %tmp2 = select i1 %arg, float 6.000000e+00, float 1.500000e+01 ; CHECK-NOT: fadd ; CHECK: ret float %tmp2 } +; Tests folding multiple expression constants from similar selects that feed a adds +define float @test1b(i1 zeroext %arg) #0 { + %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00 + %tmp1 = select i1 %arg, float 1.000000e+00, float 9.000000e+00 + %tmp2 = select i1 %arg, float 2.500000e-01, float 4.000000e+00 + %tmp3 = fadd float %tmp, %tmp1 + %tmp4 = fadd float %tmp2, %tmp1 + %tmp5 = fadd float %tmp4, %tmp3 + ret float %tmp5 +; CHECK-LABEL: @test1b( +; CHECK: %tmp5 = select i1 %arg, float 7.250000e+00, float 2.800000e+01 +; CHECK-NOT: fadd +; CHECK: ret float %tmp5 +} + ; Tests folding constants from two similar selects that feed a sub define float @test2(i1 zeroext %arg) #0 { %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00 @@ -38,3 +53,32 @@ define float @test3(i1 zeroext %arg) #0 { ; CHECK: ret float %tmp2 } +declare void @use_float(float) + +; Tests folding constants if the selects have multiple uses but +; we can fold away the binary op with a select. +define float @test4(i1 zeroext %arg) #0 { + %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00 + %tmp1 = select i1 %arg, float 1.000000e+00, float 9.000000e+00 + %tmp2 = fmul float %tmp, %tmp1 + call void @use_float(float %tmp) + ret float %tmp2 +; CHECK-LABEL: @test4( +; CHECK: select i1 %arg, float 5.000000e+00, float 6.000000e+00 +; CHECK-NEXT: select i1 %arg, float 5.000000e+00, float 5.400000e+01 +; CHECK-NEXT: call void @use_float(float %tmp) +; CHECK: ret float %tmp2 +} + +; Tests not folding constants if we cannot fold away any of the selects. +define float @test5(i1 zeroext %arg, float %div) { + %tmp = select i1 %arg, float %div, float 5.000000e+00 + %mul = fmul contract float %tmp, %tmp + call void @use_float(float %tmp) + ret float %mul +; CHECK-LABEL: @test5( +; CHECK: [[TMP:%.*]] = select i1 %arg, float %div, float 5.000000e+00 +; CHECK-NEXT: [[MUL:%.*]] = fmul contract float [[TMP]], [[TMP]] +; CHECK-NOT: fmul contract float %div, %div +; CHECK: ret float [[MUL]] +} -- 2.40.0