forked from OSchip/llvm-project
[InstCombine] fold sdiv with common shl amount in operands
(X << Z) / (Y << Z) --> X / Y
https://alive2.llvm.org/ce/z/CLKzqT
This requires a surprising "nuw" constraint because we have
to guard against immediate UB via signed-div overflow with
-1 divisor.
This extends 008a89037a
and is another transform
derived from issue #58137.
This commit is contained in:
parent
4c19439d24
commit
7b9482df3d
|
@ -862,7 +862,11 @@ static Instruction *foldIDivShl(BinaryOperator &I,
|
|||
if (!IsSigned && Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap())
|
||||
Ret = BinaryOperator::CreateUDiv(X, Y);
|
||||
|
||||
// TODO: Handle sdiv.
|
||||
// For signed div, we need 'nsw' on both shifts + 'nuw' on the divisor.
|
||||
// (X << Z) / (Y << Z) --> X / Y
|
||||
if (IsSigned && Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() &&
|
||||
Shl1->hasNoUnsignedWrap())
|
||||
Ret = BinaryOperator::CreateSDiv(X, Y);
|
||||
}
|
||||
|
||||
if (!Ret)
|
||||
|
|
|
@ -742,13 +742,11 @@ define i8 @sdiv_lshr_mul_nsw(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %div
|
||||
}
|
||||
|
||||
; TODO: (X << Z) / (Y << Z) --> X / Y
|
||||
; (X << Z) / (Y << Z) --> X / Y
|
||||
|
||||
define i8 @sdiv_shl_shl_nsw2_nuw(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_shl_nsw2_nuw(
|
||||
; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[YZ:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[XZ]], [[YZ]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[D]]
|
||||
;
|
||||
%xz = shl nsw i8 %x, %z
|
||||
|
@ -757,12 +755,13 @@ define i8 @sdiv_shl_shl_nsw2_nuw(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; extra uses are ok and 'exact' propagates
|
||||
|
||||
define i8 @sdiv_shl_shl_nsw2_nuw_exact_use(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_shl_nsw2_nuw_exact_use(
|
||||
; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: call void @use(i8 [[XZ]])
|
||||
; CHECK-NEXT: [[YZ:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[XZ]], [[YZ]]
|
||||
; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[D]]
|
||||
;
|
||||
%xz = shl nsw i8 %x, %z
|
||||
|
@ -772,6 +771,8 @@ define i8 @sdiv_shl_shl_nsw2_nuw_exact_use(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; negative test - wrong wrap
|
||||
|
||||
define i8 @sdiv_shl_shl_nsw_nuw2(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_shl_nsw_nuw2(
|
||||
; CHECK-NEXT: [[XZ:%.*]] = shl nuw i8 [[X:%.*]], [[Z:%.*]]
|
||||
|
@ -785,6 +786,8 @@ define i8 @sdiv_shl_shl_nsw_nuw2(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; negative test - wrong wrap
|
||||
|
||||
define i8 @sdiv_shl_shl_nsw_nuw(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_shl_nsw_nuw(
|
||||
; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
|
||||
|
@ -798,6 +801,8 @@ define i8 @sdiv_shl_shl_nsw_nuw(i8 %x, i8 %y, i8 %z) {
|
|||
ret i8 %d
|
||||
}
|
||||
|
||||
; negative test - wrong wrap
|
||||
|
||||
define i8 @sdiv_shl_shl_nuw_nsw2(i8 %x, i8 %y, i8 %z) {
|
||||
; CHECK-LABEL: @sdiv_shl_shl_nuw_nsw2(
|
||||
; CHECK-NEXT: [[XZ:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Z:%.*]]
|
||||
|
|
Loading…
Reference in New Issue