[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
This commit is contained in:
Roman Lebedev 2020-01-04 16:50:53 +03:00
parent d2b79c76be
commit 772ede3d5d
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
3 changed files with 43 additions and 22 deletions

View File

@ -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<Instruction>(*Op1));
return NewSel;
}
}
{
// If we are subtracting from select with one hand matching the value
// we are subtracting, sink subtraction into hands of select:

View File

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

View File

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