[llvm] [InstCombine] lshr (mul (X, 2^N + 1)), N -> add (X, lshr(X, N)) (PR #90295)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Wed May 15 18:57:19 PDT 2024
================
@@ -604,3 +604,66 @@ define <2 x i8> @ashr_known_pos_exact_vec(<2 x i8> %x, <2 x i8> %y) {
%r = ashr exact <2 x i8> %p, %y
ret <2 x i8> %r
}
+
+define i32 @lshr_mul_times_3_div_2(i32 %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]]
+; 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 %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]]
+; CHECK-NEXT: ret i32 [[LSHR]]
+;
+ %mul = mul nsw i32 %x, 3
+ %lshr = lshr exact i32 %mul, 1
+ ret i32 %lshr
+}
+
+; Negative test
+
+define i32 @lshr_mul_times_3_div_2_no_flags(i32 %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
+; CHECK-NEXT: ret i32 [[LSHR]]
+;
+ %mul = mul i32 %0, 3
+ %lshr = lshr i32 %mul, 1
+ ret i32 %lshr
+}
+
+; Negative test
+
+define i32 @mul_times_3_div_2_multiuse_lshr(i32 %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
+; CHECK-NEXT: call void @use(i32 [[MUL]])
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %mul = mul nuw i32 %x, 3
+ %res = lshr i32 %mul, 1
+ call void @use(i32 %mul)
+ ret i32 %res
+}
+
+define i32 @lshr_mul_times_3_div_2_exact_2(i32 %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]]
+; CHECK-NEXT: ret i32 [[LSHR]]
+;
+ %mul = mul nuw i32 %x, 3
+ %lshr = lshr exact i32 %mul, 1
+ ret i32 %lshr
+}
+
+declare void @use(i32)
----------------
dtcxzyw wrote:
> This is missing tests for numbers other than 3 and 1. You should test both another combination that works and one that doesn't.
@AtariDreams You can find more cases here: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/607/files
> It's also worth noting that this can still be further generalized. You now handle something like * 3 >> 1, but this also holds for * 6 >> 2 or * 12 >> 3.
We need a canonicalization that converts `(X *nuw/nsw 6) >> 2 -> (X *nuw/nsw 3) >> 1`.
https://github.com/llvm/llvm-project/pull/90295
More information about the llvm-commits
mailing list