[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 <michael_c_berg@apple.com>!

Differential Revision: https://reviews.llvm.org/D38263

llvm-svn: 314320
This commit is contained in:
Chad Rosier 2017-09-27 17:16:51 +00:00
parent c032b2beb0
commit d8b4b06f5d
2 changed files with 49 additions and 4 deletions

View File

@ -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<FPMathOperator>(&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)

View File

@ -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]]
}