Skip to content

Commit b44b4ec

Browse files
committed
[InstCombine] Fold (sub nuw X, (Y << nuw Z)) >>u exact Z --> (X >>u exact Z) sub nuw Y
This is the same fold as ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z), but with the sub operands swapped. Alive2 Proof: https://alive2.llvm.org/ce/z/2cRcdx
1 parent bd44842 commit b44b4ec

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
12751275
return NewSub;
12761276
}
12771277

1278+
// (sub nuw X, (Y << nuw Z)) >>u exact Z --> (X >>u exact Z) sub nuw Y
1279+
if (I.isExact() &&
1280+
match(Op0, m_OneUse(m_NUWSub(m_Value(X),
1281+
m_NUWShl(m_Value(Y), m_Specific(Op1)))))) {
1282+
Value *NewLshr = Builder.CreateLShr(X, Op1, "", /*isExact=*/true);
1283+
auto *NewSub = BinaryOperator::CreateNUWSub(NewLshr, Y);
1284+
NewSub->setHasNoSignedWrap(
1285+
cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap());
1286+
return NewSub;
1287+
}
1288+
12781289
auto isSuitableBinOpcode = [](Instruction::BinaryOps BinOpcode) {
12791290
switch (BinOpcode) {
12801291
default:

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,9 +468,8 @@ define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) {
468468

469469
define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {
470470
; CHECK-LABEL: @shl_sub_lshr_reverse(
471-
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
472-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]]
473-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
471+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
472+
; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]]
474473
; CHECK-NEXT: ret i32 [[LSHR]]
475474
;
476475
%shl = shl nuw i32 %x, %c
@@ -481,9 +480,8 @@ define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {
481480

482481
define i32 @shl_sub_lshr_reverse_no_nsw(i32 %x, i32 %c, i32 %y) {
483482
; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw(
484-
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
485-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]
486-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
483+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
484+
; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]
487485
; CHECK-NEXT: ret i32 [[LSHR]]
488486
;
489487
%shl = shl nuw i32 %x, %c
@@ -494,9 +492,8 @@ define i32 @shl_sub_lshr_reverse_no_nsw(i32 %x, i32 %c, i32 %y) {
494492

495493
define i32 @shl_sub_lshr_reverse_nsw_on_op1(i32 %x, i32 %c, i32 %y) {
496494
; CHECK-LABEL: @shl_sub_lshr_reverse_nsw_on_op1(
497-
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[X:%.*]], [[C:%.*]]
498-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]
499-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
495+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
496+
; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]
500497
; CHECK-NEXT: ret i32 [[LSHR]]
501498
;
502499
%shl = shl nuw nsw i32 %x, %c
@@ -541,8 +538,8 @@ define i32 @shl_sub_lshr_reverse_multiuse2(i32 %x, i32 %c, i32 %y) {
541538
; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse2(
542539
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
543540
; CHECK-NEXT: call void @use(i32 [[SHL]])
544-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]
545-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
541+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C]]
542+
; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X]]
546543
; CHECK-NEXT: ret i32 [[LSHR]]
547544
;
548545
%shl = shl nuw i32 %x, %c
@@ -757,7 +754,7 @@ define i32 @mul_splat_fold_no_nuw(i32 %x) {
757754
ret i32 %t
758755
}
759756

760-
; Negative test
757+
; Negative test
761758

762759
define i32 @mul_splat_fold_no_flags(i32 %x) {
763760
; CHECK-LABEL: @mul_splat_fold_no_flags(

0 commit comments

Comments
 (0)