[llvm] [SCEVDivision] Add SCEVDivisionPrinterPass with corresponding tests (PR #155832)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 07:08:18 PDT 2025


================
@@ -0,0 +1,210 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
+; RUN: opt < %s "-passes=print<scev-division>" -disable-output 2>&1 | FileCheck %s
+
+define i8 @add(i8 %x, i8 %y) {
+; CHECK-LABEL: 'add'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %add, %y
+; CHECK-NEXT:    Numerator: (%x + %y)
+; CHECK-NEXT:    Denominator: %y
+; CHECK-NEXT:    Quotient: 1
+; CHECK-NEXT:    Remainder: %x
+;
+  %add = add i8 %x, %y
+  %div = sdiv i8 %add, %y
+  ret i8 %div
+}
+
+define i8 @mul_add_mul(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: 'mul_add_mul'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %add, %a
+; CHECK-NEXT:    Numerator: ((2 * %c) + (%a * %b))
+; CHECK-NEXT:    Denominator: %a
+; CHECK-NEXT:    Quotient: %b
+; CHECK-NEXT:    Remainder: (2 * %c)
+;
+  %mul0 = mul nsw nuw i8 %a, %b
+  %tmp = add nsw nuw i8 %mul0, %c
+  %mul1 = mul nsw nuw i8 %a, %c
+  %add = add nsw nuw i8 %tmp, %c
+  %div = sdiv i8 %add, %a
+  ret i8 %div
+}
+
+; FIXME: We need nsw on mul.
+define i8 @mul(i8 %x, i8 %y) {
+; CHECK-LABEL: 'mul'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %mul, %y
+; CHECK-NEXT:    Numerator: (%x * %y)
+; CHECK-NEXT:    Denominator: %y
+; CHECK-NEXT:    Quotient: %x
+; CHECK-NEXT:    Remainder: 0
+;
+  %mul = mul i8 %x, %y
+  %div = sdiv i8 %mul, %y
+  ret i8 %div
+}
+
+define i8 @mul_nsw(i8 %x, i8 %y) {
+; CHECK-LABEL: 'mul_nsw'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %mul, %y
+; CHECK-NEXT:    Numerator: (%x * %y)
+; CHECK-NEXT:    Denominator: %y
+; CHECK-NEXT:    Quotient: %x
+; CHECK-NEXT:    Remainder: 0
+;
+  %mul = mul nsw i8 %x, %y
+  %div = sdiv i8 %mul, %y
+  ret i8 %div
+}
+
+; FIXME: We need nsw on mul.
+define i8 @mul_nuw(i8 %x, i8 %y) {
+; CHECK-LABEL: 'mul_nuw'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %mul, %y
+; CHECK-NEXT:    Numerator: (%x * %y)
+; CHECK-NEXT:    Denominator: %y
+; CHECK-NEXT:    Quotient: %x
+; CHECK-NEXT:    Remainder: 0
+;
+  %mul = mul nuw i8 %x, %y
+  %div = sdiv i8 %mul, %y
+  ret i8 %div
+}
+
+define i8 @add_mul_add(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: 'add_mul_add'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %mul, %a
+; CHECK-NEXT:    Numerator: ((%a + %b) * (%a + %c))
+; CHECK-NEXT:    Denominator: %a
+; CHECK-NEXT:    Quotient: 0
+; CHECK-NEXT:    Remainder: ((%a + %b) * (%a + %c))
+;
+  %add0 = add nsw nuw i8 %a, %b
+  %add1 = add nsw nuw i8 %a, %c
+  %mul = mul nsw nuw i8 %add0, %add1
+  %div = sdiv i8 %mul, %a
+  ret i8 %div
+}
+
+; for (i = 0; i < n; i++)
+;   div = i / den;
+;
+define void @addrec_iv(i8 %n, i8 %den) {
+; CHECK-LABEL: 'addrec_iv'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %i, %den
+; CHECK-NEXT:    Numerator: {0,+,1}<nuw><nsw><%loop>
+; CHECK-NEXT:    Denominator: %den
+; CHECK-NEXT:    Quotient: 0
+; CHECK-NEXT:    Remainder: {0,+,1}<nuw><nsw><%loop>
+;
+entry:
+  %guard = icmp sgt i8 %n, 0
+  br i1 %guard, label %loop, label %exit
+
+loop:
+  %i = phi i8 [ 0, %entry ], [ %i.inc, %loop ]
+  %div = sdiv i8 %i, %den
+  %i.inc = add nsw i8 %i, 1
+  %exitcond = icmp eq i8 %i.inc, %n
+  br i1 %exitcond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; for (i = 0; i < n; i++)
+;   div = (step * i) / step;
+;
+define void @addrec_step0(i8 %n, i8 %step) {
+; CHECK-LABEL: 'addrec_step0'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %num, %step
+; CHECK-NEXT:    Numerator: {0,+,%step}<nuw><nsw><%loop>
+; CHECK-NEXT:    Denominator: %step
+; CHECK-NEXT:    Quotient: {0,+,1}<nuw><nsw><%loop>
+; CHECK-NEXT:    Remainder: 0
+;
+entry:
+  %guard = icmp sgt i8 %n, 0
+  br i1 %guard, label %loop, label %exit
+
+loop:
+  %i = phi i8 [ 0, %entry ], [ %i.inc, %loop ]
+  %num = phi i8 [ 0, %entry ], [ %num.next, %loop ]
+  %div = sdiv i8 %num, %step
+  %i.inc = add nsw i8 %i, 1
+  %num.next = add nsw nuw i8 %num, %step
+  %exitcond = icmp eq i8 %i.inc, %n
+  br i1 %exitcond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; for (unsigned char i = 0; i < n; i++)
+;   if (cond)
+;     div = (step * i) / step;
+;
+; FIXME: The quotient can cause signed wrap, e.g., when %step is 0 and %n is
+; larger than 127.
+define void @addrec_step1(i8 %n, i8 %step) {
+; CHECK-LABEL: 'addrec_step1'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %num, %step
+; CHECK-NEXT:    Numerator: {0,+,%step}<nuw><nsw><%loop.header>
+; CHECK-NEXT:    Denominator: %step
+; CHECK-NEXT:    Quotient: {0,+,1}<nuw><nsw><%loop.header>
+; CHECK-NEXT:    Remainder: 0
+;
+entry:
+  %guard = icmp ne i8 %n, 0
+  br i1 %guard, label %loop.header, label %exit
+
+loop.header:
+  %i = phi i8 [ 0, %entry ], [ %i.inc, %loop.latch ]
+  %num = phi i8 [ 0, %entry ], [ %num.next, %loop.latch ]
+  %cond = freeze i1 poison
+  br i1 %cond, label %division, label %loop.latch
----------------
nikic wrote:

Yeah, this kind of inference is allowed.

https://github.com/llvm/llvm-project/pull/155832


More information about the llvm-commits mailing list