From 772ede3d5d552e0214473f247f7f98f15e596fe5 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 4 Jan 2020 16:50:53 +0300 Subject: [PATCH] [InstCombine] Sink sub into hands of select if one hand becomes zero. Part 2 (PR44426) This decreases use count of %Op0, makes one hand of select to be 0, and possibly exposes further folding potential. Name: sub %Op0, (select %Cond, %Op0, %FalseVal) -> select %Cond, 0, (sub %Op0, %FalseVal) %Op0 = %TrueVal %o = select i1 %Cond, i8 %Op0, i8 %FalseVal %r = sub i8 %Op0, %o => %n = sub i8 %Op0, %FalseVal %r = select i1 %Cond, i8 0, i8 %n Name: sub %Op0, (select %Cond, %TrueVal, %Op0) -> select %Cond, (sub %Op0, %TrueVal), 0 %Op0 = %FalseVal %o = select i1 %Cond, i8 %TrueVal, i8 %Op0 %r = sub i8 %Op0, %o => %n = sub i8 %Op0, %TrueVal %r = select i1 %Cond, i8 %n, i8 0 https://rise4fun.com/Alive/aHRt https://bugs.llvm.org/show_bug.cgi?id=44426 --- .../InstCombine/InstCombineAddSub.cpp | 27 +++++++++++++++++++ .../test/Transforms/InstCombine/sub-minmax.ll | 26 +++++++----------- .../subtract-from-one-hand-of-select.ll | 12 ++++----- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 05d13aeabe52..c723ba0a683e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1898,6 +1898,33 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { } } + { + // If we are subtracting the select with one hand matching the value + // we are subtracting from, sink subtraction into hands of select: + // sub %Op0, (select %Cond, %TrueVal, %FalseVal) + // -> + // select %Cond, (sub %Op0, %TrueVal), (sub %Op0, %FalseVal) + // This will result in select between new subtraction and 0. + Value *Cond, *TrueVal, *FalseVal; + if (match(Op1, m_OneUse(m_Select(m_Value(Cond), m_Value(TrueVal), + m_Value(FalseVal)))) && + (Op0 == TrueVal || Op0 == FalseVal)) { + // While it is really tempting to just create two subtractions and let + // InstCombine fold one of those to 0, it isn't possible to do so + // because of worklist visitation order. So ugly it is. + bool SubtractingFromTrueVal = Op0 == TrueVal; + Value *NewSub = + Builder.CreateSub(Op0, SubtractingFromTrueVal ? FalseVal : TrueVal); + Constant *Zero = Constant::getNullValue(I.getType()); + SelectInst *NewSel = + SelectInst::Create(Cond, SubtractingFromTrueVal ? Zero : NewSub, + SubtractingFromTrueVal ? NewSub : Zero); + // Preserve prof metadata if any. + NewSel->copyMetadata(cast(*Op1)); + return NewSel; + } + } + { // If we are subtracting from select with one hand matching the value // we are subtracting, sink subtraction into hands of select: diff --git a/llvm/test/Transforms/InstCombine/sub-minmax.ll b/llvm/test/Transforms/InstCombine/sub-minmax.ll index 7fb5e31d81ed..58edf37195f4 100644 --- a/llvm/test/Transforms/InstCombine/sub-minmax.ll +++ b/llvm/test/Transforms/InstCombine/sub-minmax.ll @@ -18,10 +18,8 @@ define i32 @max_na_b_minux_na(i32 %A, i32 %B) { define i32 @na_minus_max_na_b(i32 %A, i32 %B) { ; CHECK-LABEL: @na_minus_max_na_b( ; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[L0:%.*]] = icmp ult i32 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 [[B]] -; CHECK-NEXT: [[X:%.*]] = sub i32 [[NOT]], [[L1]] -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) +; CHECK-NEXT: ret i32 [[TMP1]] ; %not = xor i32 %A, -1 %l0 = icmp ult i32 %not, %B @@ -47,10 +45,8 @@ define i32 @max_b_na_minus_na(i32 %A, i32 %B) { define i32 @na_minus_max_b_na(i32 %A, i32 %B) { ; CHECK-LABEL: @na_minus_max_b_na( ; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[L0:%.*]] = icmp ugt i32 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[L1:%.*]] = select i1 [[L0]], i32 [[B]], i32 [[NOT]] -; CHECK-NEXT: [[X:%.*]] = sub i32 [[NOT]], [[L1]] -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) +; CHECK-NEXT: ret i32 [[TMP1]] ; %not = xor i32 %A, -1 %l0 = icmp ugt i32 %not, %B @@ -62,10 +58,9 @@ define i32 @na_minus_max_b_na(i32 %A, i32 %B) { define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) { ; CHECK-LABEL: @max_na_bi_minux_na( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] -; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[TMP2]] ; %B = xor i32 %Bi, -1 %not = xor i32 %A, -1 @@ -90,10 +85,9 @@ define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) { define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) { ; CHECK-LABEL: @max_bi_na_minus_na( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] -; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[TMP2]] ; %B = xor i32 %Bi, -1 %not = xor i32 %A, -1 diff --git a/llvm/test/Transforms/InstCombine/subtract-from-one-hand-of-select.ll b/llvm/test/Transforms/InstCombine/subtract-from-one-hand-of-select.ll index 1e68efa8bc52..8ff2e0ee2118 100644 --- a/llvm/test/Transforms/InstCombine/subtract-from-one-hand-of-select.ll +++ b/llvm/test/Transforms/InstCombine/subtract-from-one-hand-of-select.ll @@ -12,8 +12,8 @@ define i8 @t0_sub_from_trueval(i1 %c, i8 %Op0, i8 %FalseVal) { ; CHECK-LABEL: @t0_sub_from_trueval( -; CHECK-NEXT: [[O:%.*]] = select i1 [[C:%.*]], i8 [[OP0:%.*]], i8 [[FALSEVAL:%.*]], !prof !0 -; CHECK-NEXT: [[R:%.*]] = sub i8 [[OP0]], [[O]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[OP0:%.*]], [[FALSEVAL:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i8 0, i8 [[TMP1]], !prof !0 ; CHECK-NEXT: ret i8 [[R]] ; %o = select i1 %c, i8 %Op0, i8 %FalseVal, !prof !0 ; while there, ensure preservation of prof md @@ -22,8 +22,8 @@ define i8 @t0_sub_from_trueval(i1 %c, i8 %Op0, i8 %FalseVal) { } define i8 @t1_sub_from_falseval(i1 %c, i8 %TrueVal, i8 %Op0) { ; CHECK-LABEL: @t1_sub_from_falseval( -; CHECK-NEXT: [[O:%.*]] = select i1 [[C:%.*]], i8 [[TRUEVAL:%.*]], i8 [[OP0:%.*]], !prof !0 -; CHECK-NEXT: [[R:%.*]] = sub i8 [[OP0]], [[O]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[OP0:%.*]], [[TRUEVAL:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i8 [[TMP1]], i8 0, !prof !0 ; CHECK-NEXT: ret i8 [[R]] ; %o = select i1 %c, i8 %TrueVal, i8 %Op0, !prof !0 ; while there, ensure preservation of prof md @@ -35,8 +35,8 @@ define i8 @t1_sub_from_falseval(i1 %c, i8 %TrueVal, i8 %Op0) { define <2 x i8> @t2_vec(i1 %c, <2 x i8> %Op0, <2 x i8> %FalseVal) { ; CHECK-LABEL: @t2_vec( -; CHECK-NEXT: [[O:%.*]] = select i1 [[C:%.*]], <2 x i8> [[OP0:%.*]], <2 x i8> [[FALSEVAL:%.*]] -; CHECK-NEXT: [[R:%.*]] = sub <2 x i8> [[OP0]], [[O]] +; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[OP0:%.*]], [[FALSEVAL:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], <2 x i8> zeroinitializer, <2 x i8> [[TMP1]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %o = select i1 %c, <2 x i8> %Op0, <2 x i8> %FalseVal