Skip to content

Commit 8a4266a

Browse files
authored
[InstSimplify] Fold u/sdiv exact (mul nsw/nuw X, C), C --> X when C is not a power of 2 (#76445)
Alive2: https://alive2.llvm.org/ce/z/3D9R7d
1 parent a700298 commit 8a4266a

File tree

2 files changed

+116
-7
lines changed

2 files changed

+116
-7
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,14 +1189,26 @@ static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
11891189
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q, MaxRecurse))
11901190
return V;
11911191

1192-
// If this is an exact divide by a constant, then the dividend (Op0) must have
1193-
// at least as many trailing zeros as the divisor to divide evenly. If it has
1194-
// less trailing zeros, then the result must be poison.
11951192
const APInt *DivC;
1196-
if (IsExact && match(Op1, m_APInt(DivC)) && DivC->countr_zero()) {
1197-
KnownBits KnownOp0 = computeKnownBits(Op0, /* Depth */ 0, Q);
1198-
if (KnownOp0.countMaxTrailingZeros() < DivC->countr_zero())
1199-
return PoisonValue::get(Op0->getType());
1193+
if (IsExact && match(Op1, m_APInt(DivC))) {
1194+
// If this is an exact divide by a constant, then the dividend (Op0) must
1195+
// have at least as many trailing zeros as the divisor to divide evenly. If
1196+
// it has less trailing zeros, then the result must be poison.
1197+
if (DivC->countr_zero()) {
1198+
KnownBits KnownOp0 = computeKnownBits(Op0, /* Depth */ 0, Q);
1199+
if (KnownOp0.countMaxTrailingZeros() < DivC->countr_zero())
1200+
return PoisonValue::get(Op0->getType());
1201+
}
1202+
1203+
// udiv exact (mul nsw X, C), C --> X
1204+
// sdiv exact (mul nuw X, C), C --> X
1205+
// where C is not a power of 2.
1206+
Value *X;
1207+
if (!DivC->isPowerOf2() &&
1208+
(Opcode == Instruction::UDiv
1209+
? match(Op0, m_NSWMul(m_Value(X), m_Specific(Op1)))
1210+
: match(Op0, m_NUWMul(m_Value(X), m_Specific(Op1)))))
1211+
return X;
12001212
}
12011213

12021214
return nullptr;

llvm/test/Transforms/InstSimplify/div.ll

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,3 +567,100 @@ define <2 x i8> @sdiv_vec_multi_one_bit_divisor(<2 x i8> %x, <2 x i8> %y) {
567567
%res = sdiv <2 x i8> %y, %and
568568
ret <2 x i8> %res
569569
}
570+
571+
define i8 @udiv_exact_mul_nsw(i8 %x) {
572+
; CHECK-LABEL: @udiv_exact_mul_nsw(
573+
; CHECK-NEXT: ret i8 [[X:%.*]]
574+
;
575+
%a = mul nsw i8 %x, 24
576+
%b = udiv exact i8 %a, 24
577+
ret i8 %b
578+
}
579+
580+
define i8 @sdiv_exact_mul_nuw(i8 %x) {
581+
; CHECK-LABEL: @sdiv_exact_mul_nuw(
582+
; CHECK-NEXT: ret i8 [[X:%.*]]
583+
;
584+
%a = mul nuw i8 %x, 24
585+
%b = sdiv exact i8 %a, 24
586+
ret i8 %b
587+
}
588+
589+
; Negative tests
590+
591+
define i8 @udiv_exact_mul_nsw_mismatch(i8 %x) {
592+
; CHECK-LABEL: @udiv_exact_mul_nsw_mismatch(
593+
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 24
594+
; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 12
595+
; CHECK-NEXT: ret i8 [[B]]
596+
;
597+
%a = mul nsw i8 %x, 24
598+
%b = udiv exact i8 %a, 12
599+
ret i8 %b
600+
}
601+
602+
define i8 @udiv_exact_mul_nsw_power_of_2(i8 %x) {
603+
; CHECK-LABEL: @udiv_exact_mul_nsw_power_of_2(
604+
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 8
605+
; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 8
606+
; CHECK-NEXT: ret i8 [[B]]
607+
;
608+
%a = mul nsw i8 %x, 8
609+
%b = udiv exact i8 %a, 8
610+
ret i8 %b
611+
}
612+
613+
define i8 @sdiv_exact_mul_nuw_power_of_2(i8 %x) {
614+
; CHECK-LABEL: @sdiv_exact_mul_nuw_power_of_2(
615+
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 8
616+
; CHECK-NEXT: [[B:%.*]] = sdiv exact i8 [[A]], 8
617+
; CHECK-NEXT: ret i8 [[B]]
618+
;
619+
%a = mul nuw i8 %x, 8
620+
%b = sdiv exact i8 %a, 8
621+
ret i8 %b
622+
}
623+
624+
define i8 @udiv_exact_mul(i8 %x) {
625+
; CHECK-LABEL: @udiv_exact_mul(
626+
; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 24
627+
; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 24
628+
; CHECK-NEXT: ret i8 [[B]]
629+
;
630+
%a = mul i8 %x, 24
631+
%b = udiv exact i8 %a, 24
632+
ret i8 %b
633+
}
634+
635+
define i8 @sdiv_exact_mul(i8 %x) {
636+
; CHECK-LABEL: @sdiv_exact_mul(
637+
; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 24
638+
; CHECK-NEXT: [[B:%.*]] = sdiv exact i8 [[A]], 24
639+
; CHECK-NEXT: ret i8 [[B]]
640+
;
641+
%a = mul i8 %x, 24
642+
%b = sdiv exact i8 %a, 24
643+
ret i8 %b
644+
}
645+
646+
define i8 @udiv_mul_nsw(i8 %x) {
647+
; CHECK-LABEL: @udiv_mul_nsw(
648+
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 24
649+
; CHECK-NEXT: [[B:%.*]] = udiv i8 [[A]], 24
650+
; CHECK-NEXT: ret i8 [[B]]
651+
;
652+
%a = mul nsw i8 %x, 24
653+
%b = udiv i8 %a, 24
654+
ret i8 %b
655+
}
656+
657+
define i8 @sdiv_mul_nuw(i8 %x) {
658+
; CHECK-LABEL: @sdiv_mul_nuw(
659+
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 24
660+
; CHECK-NEXT: [[B:%.*]] = sdiv i8 [[A]], 24
661+
; CHECK-NEXT: ret i8 [[B]]
662+
;
663+
%a = mul nuw i8 %x, 24
664+
%b = sdiv i8 %a, 24
665+
ret i8 %b
666+
}

0 commit comments

Comments
 (0)