Skip to content

Commit f7e13cd

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. Proof: https://alive2.llvm.org/ce/z/2cRcdx
1 parent ad02eb5 commit f7e13cd

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,7 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
12591259
match(Op1, m_SpecificIntAllowPoison(BitWidth - 1)))
12601260
return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty);
12611261

1262-
// ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z),
1262+
// ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z)
12631263
Value *Y;
12641264
if (I.isExact() &&
12651265
match(Op0, m_OneUse(m_NUWSub(m_NUWShl(m_Value(X), m_Specific(Op1)),
@@ -1271,6 +1271,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
12711271
return NewSub;
12721272
}
12731273

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

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,8 @@ define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) {
466466

467467
define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {
468468
; CHECK-LABEL: @shl_sub_lshr_reverse(
469-
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
470-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]]
471-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
469+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
470+
; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]]
472471
; CHECK-NEXT: ret i32 [[LSHR]]
473472
;
474473
%shl = shl nuw i32 %x, %c

0 commit comments

Comments
 (0)