Skip to content

Commit dde583e

Browse files
committed
[InstCombine] Fold adds + shifts with nsw and nuw flags
[InstCombine] Fold adds + shifts with nsw and nuw flags Proofs: https://alive2.llvm.org/ce/z/kDVTiL https://alive2.llvm.org/ce/z/wORNYm
1 parent a9a8caf commit dde583e

File tree

3 files changed

+20
-112
lines changed

3 files changed

+20
-112
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

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

1262+
// If both the add and the shift are nuw, then:
1263+
// ((X << Z) + Y) nuw >>u Z --> X + (Y >>u Z) nuw
1264+
Value *Y;
1265+
if (match(Op0, m_OneUse(m_c_NUWAdd(m_NUWShl(m_Value(X), m_Specific(Op1)),
1266+
m_Value(Y))))) {
1267+
Value *NewLshr = Builder.CreateLShr(Y, Op1, "", I.isExact());
1268+
auto *newAdd = BinaryOperator::CreateNUWAdd(NewLshr, X);
1269+
if (auto *Op0Bin = cast<OverflowingBinaryOperator>(Op0))
1270+
newAdd->setHasNoSignedWrap(Op0Bin->hasNoSignedWrap());
1271+
return newAdd;
1272+
}
1273+
12621274
if (match(Op1, m_APInt(C))) {
12631275
unsigned ShAmtC = C->getZExtValue();
12641276
auto *II = dyn_cast<IntrinsicInst>(Op0);
@@ -1275,7 +1287,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
12751287
return new ZExtInst(Cmp, Ty);
12761288
}
12771289

1278-
Value *X;
12791290
const APInt *C1;
12801291
if (match(Op0, m_Shl(m_Value(X), m_APInt(C1))) && C1->ult(BitWidth)) {
12811292
if (C1->ult(ShAmtC)) {
@@ -1320,7 +1331,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
13201331
// ((X << C) + Y) >>u C --> (X + (Y >>u C)) & (-1 >>u C)
13211332
// TODO: Consolidate with the more general transform that starts from shl
13221333
// (the shifts are in the opposite order).
1323-
Value *Y;
13241334
if (match(Op0,
13251335
m_OneUse(m_c_Add(m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))),
13261336
m_Value(Y))))) {

llvm/test/Transforms/InstCombine/ashr-lshr.ll

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -604,51 +604,3 @@ define <2 x i8> @ashr_known_pos_exact_vec(<2 x i8> %x, <2 x i8> %y) {
604604
%r = ashr exact <2 x i8> %p, %y
605605
ret <2 x i8> %r
606606
}
607-
608-
define i32 @ashr_mul_times_3_div_2(i32 %0) {
609-
; CHECK-LABEL: @ashr_mul_times_3_div_2(
610-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], 3
611-
; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[MUL]], 1
612-
; CHECK-NEXT: ret i32 [[ASHR]]
613-
;
614-
%mul = mul nsw nuw i32 %0, 3
615-
%ashr = ashr i32 %mul, 1
616-
ret i32 %ashr
617-
}
618-
619-
define i32 @ashr_mul_times_3_div_2_exact(i32 %x) {
620-
; CHECK-LABEL: @ashr_mul_times_3_div_2_exact(
621-
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 3
622-
; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i32 [[MUL]], 1
623-
; CHECK-NEXT: ret i32 [[ASHR]]
624-
;
625-
%mul = mul nsw i32 %x, 3
626-
%ashr = ashr exact i32 %mul, 1
627-
ret i32 %ashr
628-
}
629-
630-
define i32 @mul_times_3_div_2_multiuse(i32 %x) {
631-
; CHECK-LABEL: @mul_times_3_div_2_multiuse(
632-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 3
633-
; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[MUL]], 1
634-
; CHECK-NEXT: call void @use(i32 [[MUL]])
635-
; CHECK-NEXT: ret i32 [[RES]]
636-
;
637-
%mul = mul nuw i32 %x, 3
638-
%res = ashr i32 %mul, 1
639-
call void @use (i32 %mul)
640-
ret i32 %res
641-
}
642-
643-
define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
644-
; CHECK-LABEL: @ashr_mul_times_3_div_2_exact_2(
645-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 3
646-
; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i32 [[MUL]], 1
647-
; CHECK-NEXT: ret i32 [[ASHR]]
648-
;
649-
%mul = mul nuw i32 %x, 3
650-
%ashr = ashr exact i32 %mul, 1
651-
ret i32 %ashr
652-
}
653-
654-
declare void @use(i32)

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -360,24 +360,12 @@ define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) {
360360
ret <3 x i14> %t
361361
}
362362

363-
; Negative tests
364-
365-
define i32 @mul_times_3_div_2(i32 %x) {
366-
; CHECK-LABEL: @mul_times_3_div_2(
367-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X:%.*]], 3
368-
; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[MUL]], 1
369-
; CHECK-NEXT: ret i32 [[RES]]
370-
;
371-
%mul = mul nsw nuw i32 %x, 3
372-
%res = lshr i32 %mul, 1
373-
ret i32 %res
374-
}
363+
; Negative test
375364

376365
define i32 @shl_add_lshr(i32 %x, i32 %c, i32 %y) {
377366
; CHECK-LABEL: @shl_add_lshr(
378-
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
379-
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Y:%.*]]
380-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[ADD]], [[C]]
367+
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
368+
; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP1]], [[X:%.*]]
381369
; CHECK-NEXT: ret i32 [[LSHR]]
382370
;
383371
%shl = shl nuw i32 %x, %c
@@ -386,40 +374,7 @@ define i32 @shl_add_lshr(i32 %x, i32 %c, i32 %y) {
386374
ret i32 %lshr
387375
}
388376

389-
define i32 @lshr_mul_times_3_div_2_nuw(i32 %0) {
390-
; CHECK-LABEL: @lshr_mul_times_3_div_2_nuw(
391-
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
392-
; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
393-
; CHECK-NEXT: ret i32 [[LSHR]]
394-
;
395-
%mul = mul nuw i32 %0, 3
396-
%lshr = lshr i32 %mul, 1
397-
ret i32 %lshr
398-
}
399-
400-
define i32 @lshr_mul_times_3_div_2_nsw(i32 %0) {
401-
; CHECK-LABEL: @lshr_mul_times_3_div_2_nsw(
402-
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP0:%.*]], 3
403-
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[MUL]], 1
404-
; CHECK-NEXT: ret i32 [[LSHR]]
405-
;
406-
%mul = mul nsw i32 %0, 3
407-
%lshr = lshr i32 %mul, 1
408-
ret i32 %lshr
409-
}
410-
411-
; Negative tests
412-
413-
define i32 @mul_times_3_div_2_no_flag(i32 %x) {
414-
; CHECK-LABEL: @mul_times_3_div_2_no_flag(
415-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 3
416-
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[MUL]], 1
417-
; CHECK-NEXT: ret i32 [[LSHR]]
418-
;
419-
%mul = mul i32 %x, 3
420-
%lshr = lshr i32 %mul, 1
421-
ret i32 %lshr
422-
}
377+
; Negative test
423378

424379
define i32 @shl_add_lshr_neg(i32 %x, i32 %y, i32 %z) {
425380
; CHECK-LABEL: @shl_add_lshr_neg(
@@ -445,6 +400,8 @@ define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {
445400
ret i32 %t
446401
}
447402

403+
; Negative test
404+
448405
define i32 @shl_add_lshr_multiuse(i32 %x, i32 %y, i32 %z) {
449406
; CHECK-LABEL: @shl_add_lshr_multiuse(
450407
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
@@ -460,19 +417,6 @@ define i32 @shl_add_lshr_multiuse(i32 %x, i32 %y, i32 %z) {
460417
ret i32 %res
461418
}
462419

463-
define i32 @mul_times_3_div_2_multiuse(i32 %x) {
464-
; CHECK-LABEL: @mul_times_3_div_2_multiuse(
465-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 3
466-
; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[MUL]], 1
467-
; CHECK-NEXT: call void @use(i32 [[MUL]])
468-
; CHECK-NEXT: ret i32 [[RES]]
469-
;
470-
%mul = mul nuw i32 %x, 3
471-
%res = lshr i32 %mul, 1
472-
call void @use (i32 %mul)
473-
ret i32 %res
474-
}
475-
476420
define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
477421
; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(
478422
; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537
@@ -484,6 +428,8 @@ define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
484428
ret i32 %t
485429
}
486430

431+
; Negative test
432+
487433
define i32 @mul_splat_fold_no_nuw(i32 %x) {
488434
; CHECK-LABEL: @mul_splat_fold_no_nuw(
489435
; CHECK-NEXT: [[M:%.*]] = mul nsw i32 [[X:%.*]], 65537

0 commit comments

Comments
 (0)