[llvm] [InstCombine] Fold (X << Y) / (X << Z) -> 1 << Y >> Z (PR #68863)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 13 00:52:02 PDT 2023
================
@@ -1025,3 +1026,188 @@ define i8 @udiv_shl_no_overflow(i8 %x, i8 %y) {
%mul = udiv i8 %x, %min
ret i8 %mul
}
+
+; (X<<Y) / (X<<Z) -> 1 << Y >> Z
+
+define i32 @sdiv_shl_pair_const(i32 %a) {
+; CHECK-LABEL: @sdiv_shl_pair_const(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 2
+;
+entry:
+ %lhs = shl nsw i32 %a, 2
+ %rhs = shl nsw i32 %a, 1
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair_const(i32 %a) {
+; CHECK-LABEL: @udiv_shl_pair_const(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 2
+;
+entry:
+ %lhs = shl nuw i32 %a, 2
+ %rhs = shl nuw i32 %a, 1
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @sdiv_shl_pair1(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_shl_pair1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw nsw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nsw i32 %a, %x
+ %rhs = shl nuw nsw i32 %a, %y
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @sdiv_shl_pair2(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_shl_pair2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw nsw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw nsw i32 %a, %x
+ %rhs = shl nsw i32 %a, %y
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @sdiv_shl_pair3(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_shl_pair3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw nsw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw nsw i32 %a, %x
+ %rhs = shl nsw i32 %a, %y
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair1(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw i32 %a, %x
+ %rhs = shl nuw i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair2(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw nsw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw nsw i32 %a, %x
+ %rhs = shl nuw i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair3(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHL_DIVIDEND:%.*]] = shl nuw i32 1, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[SHL_DIVIDEND]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw i32 %a, %x
+ %rhs = shl nuw nsw i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @sdiv_shl_pair_overflow_fail1(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_shl_pair_overflow_fail1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LHS:%.*]] = shl i32 [[A:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[RHS:%.*]] = shl nsw i32 [[A]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl i32 %a, %x
+ %rhs = shl nsw i32 %a, %y
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @sdiv_shl_pair_overflow_fail2(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_shl_pair_overflow_fail2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LHS:%.*]] = shl nsw i32 [[A:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[RHS:%.*]] = shl nuw i32 [[A]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nsw i32 %a, %x
+ %rhs = shl nuw i32 %a, %y
+ %div = sdiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair_overflow_fail1(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair_overflow_fail1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LHS:%.*]] = shl nsw i32 [[A:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[RHS:%.*]] = shl nuw i32 [[A]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nsw i32 %a, %x
+ %rhs = shl nuw i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair_overflow_fail2(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair_overflow_fail2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LHS:%.*]] = shl nsw i32 [[A:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[RHS:%.*]] = shl i32 [[A]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nsw i32 %a, %x
+ %rhs = shl i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
+
+define i32 @udiv_shl_pair_overflow_fail3(i32 %a, i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_shl_pair_overflow_fail3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LHS:%.*]] = shl nuw nsw i32 [[A:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[RHS:%.*]] = shl i32 [[A]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %lhs = shl nuw nsw i32 %a, %x
+ %rhs = shl i32 %a, %y
+ %div = udiv i32 %lhs, %rhs
+ ret i32 %div
+}
----------------
nikic wrote:
Can you please also add a negative test where the LHS operands are not the same?
https://github.com/llvm/llvm-project/pull/68863
More information about the llvm-commits
mailing list