Unverified Commit dfe1d35c authored by Yingwei Zheng's avatar Yingwei Zheng Committed by GitHub
Browse files

[InstCombine] Propagate NSW/NUW flags for `(X - Y) - Z -> X - (Y + Z)` (#72693)

parent 5a305cea
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -2191,8 +2191,15 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {

  // ((X - Y) - Op1)  -->  X - (Y + Op1)
  if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y))))) {
    Value *Add = Builder.CreateAdd(Y, Op1);
    return BinaryOperator::CreateSub(X, Add);
    OverflowingBinaryOperator *LHSSub = cast<OverflowingBinaryOperator>(Op0);
    bool HasNUW = I.hasNoUnsignedWrap() && LHSSub->hasNoUnsignedWrap();
    bool HasNSW = HasNUW && I.hasNoSignedWrap() && LHSSub->hasNoSignedWrap();
    Value *Add = Builder.CreateAdd(Y, Op1, "", /* HasNUW */ HasNUW,
                                   /* HasNSW */ HasNSW);
    BinaryOperator *Sub = BinaryOperator::CreateSub(X, Add);
    Sub->setHasNoUnsignedWrap(HasNUW);
    Sub->setHasNoSignedWrap(HasNSW);
    return Sub;
  }

  // (~X) - (~Y) --> Y - X
+69 −1
Original line number Diff line number Diff line
@@ -17,14 +17,82 @@ define i8 @t0(i8 %x, i8 %y, i8 %z) {
  ret i8 %r
}

; No flags are propagated
; NSW/NUW flags are propagated
define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags(
; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub nuw nsw i8 %x, %y
  %r = sub nuw nsw i8 %o0, %z
  ret i8 %r
}

; NUW flags are propagated
define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_nuw_only(
; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub nuw i8 %x, %y
  %r = sub nuw i8 %o0, %z
  ret i8 %r
}

; Negative tests
define i8 @t1_flags_sub_nsw_sub(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_sub_nsw_sub(
; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub nsw i8 %x, %y
  %r = sub i8 %o0, %z
  ret i8 %r
}

define i8 @t1_flags_nuw_first(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_nuw_first(
; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub nuw i8 %x, %y
  %r = sub i8 %o0, %z
  ret i8 %r
}

define i8 @t1_flags_nuw_second(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_nuw_second(
; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub i8 %x, %y
  %r = sub nuw i8 %o0, %z
  ret i8 %r
}

define i8 @t1_flags_nuw_nsw_first(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_nuw_nsw_first(
; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub nuw nsw i8 %x, %y
  %r = sub i8 %o0, %z
  ret i8 %r
}

define i8 @t1_flags_nuw_nsw_second(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @t1_flags_nuw_nsw_second(
; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT:    ret i8 [[R]]
;
  %o0 = sub i8 %x, %y
  %r = sub nuw nsw i8 %o0, %z
  ret i8 %r
}