Skip to content

Commit

Permalink
[InstCombine] Add freeze for lshr (mul (X, 2^N + 1)), N -> add (X, ls…
Browse files Browse the repository at this point in the history
…hr(X, N))
  • Loading branch information
AreaZR committed Jul 18, 2024
1 parent d00b355 commit b4bb27f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,7 +1499,7 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
return replaceInstUsesWith(I, X);

// lshr (mul nuw (X, 2^N + 1)), N -> add nuw (X, lshr(X, N))
if (Op0->hasOneUse()) {
if (Op0->hasOneUse() && isGuaranteedNotToBeUndef(X, &AC, &I, &DT)) {
auto *NewAdd = BinaryOperator::CreateNUWAdd(
X, Builder.CreateLShr(X, ConstantInt::get(Ty, ShAmtC), "",
I.isExact()));
Expand Down Expand Up @@ -1528,7 +1528,8 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
}

// lshr (mul nsw (X, 2^N + 1)), N -> add nsw (X, lshr(X, N))
if (match(Op0, m_OneUse(m_NSWMul(m_Value(X), m_APInt(MulC))))) {
if (match(Op0, m_OneUse(m_NSWMul(m_Value(X), m_APInt(MulC)))) &&
isGuaranteedNotToBeUndef(X, &AC, &I, &DT)) {
if (BitWidth > 2 && (*MulC - 1).isPowerOf2() &&
MulC->logBase2() == ShAmtC) {
return BinaryOperator::CreateNSWAdd(
Expand Down
53 changes: 33 additions & 20 deletions llvm/test/Transforms/InstCombine/ashr-lshr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ define <2 x i8> @ashr_known_pos_exact_vec(<2 x i8> %x, <2 x i8> %y) {
ret <2 x i8> %r
}

define i32 @lshr_mul_times_3_div_2(i32 %0) {
define i32 @lshr_mul_times_3_div_2(i32 noundef %0) {
; CHECK-LABEL: @lshr_mul_times_3_div_2(
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
Expand All @@ -616,7 +616,20 @@ define i32 @lshr_mul_times_3_div_2(i32 %0) {
ret i32 %lshr
}

define i32 @lshr_mul_times_3_div_2_exact(i32 %x) {
; Negative test

define i32 @lshr_mul_times_3_div_2_undef(i32 %0) {
; CHECK-LABEL: @lshr_mul_times_3_div_2_undef(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], 3
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[MUL]], 1
; CHECK-NEXT: ret i32 [[LSHR]]
;
%mul = mul nsw nuw i32 %0, 3
%lshr = lshr i32 %mul, 1
ret i32 %lshr
}

define i32 @lshr_mul_times_3_div_2_exact(i32 noundef %x) {
; CHECK-LABEL: @lshr_mul_times_3_div_2_exact(
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 1
; CHECK-NEXT: [[LSHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand All @@ -629,7 +642,7 @@ define i32 @lshr_mul_times_3_div_2_exact(i32 %x) {

; Negative test

define i32 @lshr_mul_times_3_div_2_no_flags(i32 %0) {
define i32 @lshr_mul_times_3_div_2_no_flags(i32 noundef %0) {
; CHECK-LABEL: @lshr_mul_times_3_div_2_no_flags(
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 3
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[MUL]], 1
Expand All @@ -642,7 +655,7 @@ define i32 @lshr_mul_times_3_div_2_no_flags(i32 %0) {

; Negative test

define i32 @mul_times_3_div_2_multiuse_lshr(i32 %x) {
define i32 @mul_times_3_div_2_multiuse_lshr(i32 noundef %x) {
; CHECK-LABEL: @mul_times_3_div_2_multiuse_lshr(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 3
; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[MUL]], 1
Expand All @@ -655,7 +668,7 @@ define i32 @mul_times_3_div_2_multiuse_lshr(i32 %x) {
ret i32 %res
}

define i32 @lshr_mul_times_3_div_2_exact_2(i32 %x) {
define i32 @lshr_mul_times_3_div_2_exact_2(i32 noundef %x) {
; CHECK-LABEL: @lshr_mul_times_3_div_2_exact_2(
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 1
; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X]]
Expand All @@ -666,7 +679,7 @@ define i32 @lshr_mul_times_3_div_2_exact_2(i32 %x) {
ret i32 %lshr
}

define i32 @lshr_mul_times_5_div_4(i32 %0) {
define i32 @lshr_mul_times_5_div_4(i32 noundef %0) {
; CHECK-LABEL: @lshr_mul_times_5_div_4(
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 2
; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
Expand All @@ -677,7 +690,7 @@ define i32 @lshr_mul_times_5_div_4(i32 %0) {
ret i32 %lshr
}

define i32 @lshr_mul_times_5_div_4_exact(i32 %x) {
define i32 @lshr_mul_times_5_div_4_exact(i32 noundef %x) {
; CHECK-LABEL: @lshr_mul_times_5_div_4_exact(
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 2
; CHECK-NEXT: [[LSHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand All @@ -690,7 +703,7 @@ define i32 @lshr_mul_times_5_div_4_exact(i32 %x) {

; Negative test

define i32 @lshr_mul_times_5_div_4_no_flags(i32 %0) {
define i32 @lshr_mul_times_5_div_4_no_flags(i32 noundef %0) {
; CHECK-LABEL: @lshr_mul_times_5_div_4_no_flags(
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 5
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[MUL]], 2
Expand All @@ -703,7 +716,7 @@ define i32 @lshr_mul_times_5_div_4_no_flags(i32 %0) {

; Negative test

define i32 @mul_times_5_div_4_multiuse_lshr(i32 %x) {
define i32 @mul_times_5_div_4_multiuse_lshr(i32 noundef %x) {
; CHECK-LABEL: @mul_times_5_div_4_multiuse_lshr(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 5
; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[MUL]], 2
Expand All @@ -716,7 +729,7 @@ define i32 @mul_times_5_div_4_multiuse_lshr(i32 %x) {
ret i32 %res
}

define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {
define i32 @lshr_mul_times_5_div_4_exact_2(i32 noundef %x) {
; CHECK-LABEL: @lshr_mul_times_5_div_4_exact_2(
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 2
; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X]]
Expand All @@ -727,7 +740,7 @@ define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {
ret i32 %lshr
}

define i32 @ashr_mul_times_3_div_2(i32 %0) {
define i32 @ashr_mul_times_3_div_2(i32 noundef %0) {
; CHECK-LABEL: @ashr_mul_times_3_div_2(
; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 1
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
Expand All @@ -738,7 +751,7 @@ define i32 @ashr_mul_times_3_div_2(i32 %0) {
ret i32 %ashr
}

define i32 @ashr_mul_times_3_div_2_exact(i32 %x) {
define i32 @ashr_mul_times_3_div_2_exact(i32 noundef %x) {
; CHECK-LABEL: @ashr_mul_times_3_div_2_exact(
; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 1
; CHECK-NEXT: [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand All @@ -751,7 +764,7 @@ define i32 @ashr_mul_times_3_div_2_exact(i32 %x) {

; Negative test

define i32 @ashr_mul_times_3_div_2_no_flags(i32 %0) {
define i32 @ashr_mul_times_3_div_2_no_flags(i32 noundef %0) {
; CHECK-LABEL: @ashr_mul_times_3_div_2_no_flags(
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 3
; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[MUL]], 1
Expand All @@ -764,7 +777,7 @@ define i32 @ashr_mul_times_3_div_2_no_flags(i32 %0) {

; Negative test

define i32 @ashr_mul_times_3_div_2_no_nsw(i32 %0) {
define i32 @ashr_mul_times_3_div_2_no_nsw(i32 noundef %0) {
; CHECK-LABEL: @ashr_mul_times_3_div_2_no_nsw(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[TMP0:%.*]], 3
; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[MUL]], 1
Expand All @@ -777,7 +790,7 @@ define i32 @ashr_mul_times_3_div_2_no_nsw(i32 %0) {

; Negative test

define i32 @mul_times_3_div_2_multiuse_ashr(i32 %x) {
define i32 @mul_times_3_div_2_multiuse_ashr(i32 noundef %x) {
; CHECK-LABEL: @mul_times_3_div_2_multiuse_ashr(
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 3
; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[MUL]], 1
Expand All @@ -790,7 +803,7 @@ define i32 @mul_times_3_div_2_multiuse_ashr(i32 %x) {
ret i32 %res
}

define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
define i32 @ashr_mul_times_3_div_2_exact_2(i32 noundef %x) {
; CHECK-LABEL: @ashr_mul_times_3_div_2_exact_2(
; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 1
; CHECK-NEXT: [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand All @@ -801,7 +814,7 @@ define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
ret i32 %ashr
}

define i32 @ashr_mul_times_5_div_4(i32 %0) {
define i32 @ashr_mul_times_5_div_4(i32 noundef %0) {
; CHECK-LABEL: @ashr_mul_times_5_div_4(
; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 2
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
Expand All @@ -825,7 +838,7 @@ define i32 @ashr_mul_times_5_div_4_exact(i32 %x) {

; Negative test

define i32 @ashr_mul_times_5_div_4_no_flags(i32 %0) {
define i32 @ashr_mul_times_5_div_4_no_flags(i32 noundef %0) {
; CHECK-LABEL: @ashr_mul_times_5_div_4_no_flags(
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 5
; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[MUL]], 2
Expand All @@ -838,7 +851,7 @@ define i32 @ashr_mul_times_5_div_4_no_flags(i32 %0) {

; Negative test

define i32 @mul_times_5_div_4_multiuse_ashr(i32 %x) {
define i32 @mul_times_5_div_4_multiuse_ashr(i32 noundef %x) {
; CHECK-LABEL: @mul_times_5_div_4_multiuse_ashr(
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 5
; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[MUL]], 2
Expand All @@ -851,7 +864,7 @@ define i32 @mul_times_5_div_4_multiuse_ashr(i32 %x) {
ret i32 %res
}

define i32 @ashr_mul_times_5_div_4_exact_2(i32 %x) {
define i32 @ashr_mul_times_5_div_4_exact_2(i32 noundef %x) {
; CHECK-LABEL: @ashr_mul_times_5_div_4_exact_2(
; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 2
; CHECK-NEXT: [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/lshr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
ret i32 %t
}

define i32 @mul_splat_fold_no_nuw(i32 %x) {
define i32 @mul_splat_fold_no_nuw(i32 noundef %x) {
; CHECK-LABEL: @mul_splat_fold_no_nuw(
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16
; CHECK-NEXT: [[T:%.*]] = add nsw i32 [[TMP1]], [[X]]
Expand Down

0 comments on commit b4bb27f

Please sign in to comment.