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

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 29 02:49:50 PDT 2025


https://github.com/kasuga-fj updated https://github.com/llvm/llvm-project/pull/155832

>From acdb7dcd259f24a517397686f6726eca8748c378 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Tue, 26 Aug 2025 06:57:03 +0000
Subject: [PATCH 1/3] [SCEVDivision] Add printer pass

---
 .../llvm/Analysis/ScalarEvolutionDivision.h   |   9 +
 llvm/lib/Analysis/ScalarEvolutionDivision.cpp |  32 +++
 llvm/lib/Passes/PassBuilder.cpp               |   1 +
 llvm/lib/Passes/PassRegistry.def              |   1 +
 .../Analysis/ScalarEvolutionDivision/sdiv.ll  | 210 ++++++++++++++++++
 llvm/utils/UpdateTestChecks/common.py         |   1 +
 6 files changed, 254 insertions(+)
 create mode 100644 llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll

diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
index 3283d438ccb51..cf6db50fddbe3 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
@@ -68,6 +68,15 @@ struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
   const SCEV *Denominator, *Quotient, *Remainder, *Zero, *One;
 };
 
+class SCEVDivisionPrinterPass : public PassInfoMixin<SCEVDivisionPrinterPass> {
+  raw_ostream &OS;
+  void runImpl(Function &F, ScalarEvolution &SE);
+
+public:
+  explicit SCEVDivisionPrinterPass(raw_ostream &OS) : OS(OS) {}
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
 } // end namespace llvm
 
 #endif // LLVM_ANALYSIS_SCALAREVOLUTIONDIVISION_H
diff --git a/llvm/lib/Analysis/ScalarEvolutionDivision.cpp b/llvm/lib/Analysis/ScalarEvolutionDivision.cpp
index d03930d9e2d99..bce41f9f5329e 100644
--- a/llvm/lib/Analysis/ScalarEvolutionDivision.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionDivision.cpp
@@ -15,10 +15,14 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/Support/Casting.h"
 #include <cassert>
 #include <cstdint>
 
+#define DEBUG_TYPE "scev-division"
+
 namespace llvm {
 class Type;
 } // namespace llvm
@@ -257,3 +261,31 @@ void SCEVDivision::cannotDivide(const SCEV *Numerator) {
   Quotient = Zero;
   Remainder = Numerator;
 }
+
+void SCEVDivisionPrinterPass::runImpl(Function &F, ScalarEvolution &SE) {
+  OS << "Printing analysis 'Scalar Evolution Division' for function '"
+     << F.getName() << "':\n";
+  for (Instruction &Inst : instructions(F)) {
+    BinaryOperator *Div = dyn_cast<BinaryOperator>(&Inst);
+    if (!Div || Div->getOpcode() != Instruction::SDiv)
+      continue;
+
+    const SCEV *Numerator = SE.getSCEV(Div->getOperand(0));
+    const SCEV *Denominator = SE.getSCEV(Div->getOperand(1));
+    const SCEV *Quotient, *Remainder;
+    SCEVDivision::divide(SE, Numerator, Denominator, &Quotient, &Remainder);
+
+    OS << "Instruction: " << *Div << "\n";
+    OS.indent(2) << "Numerator: " << *Numerator << "\n";
+    OS.indent(2) << "Denominator: " << *Denominator << "\n";
+    OS.indent(2) << "Quotient: " << *Quotient << "\n";
+    OS.indent(2) << "Remainder: " << *Remainder << "\n";
+  }
+}
+
+PreservedAnalyses SCEVDivisionPrinterPass::run(Function &F,
+                                               FunctionAnalysisManager &AM) {
+  ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
+  runImpl(F, SE);
+  return PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index b7edeea082762..d75304b5e11f6 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -69,6 +69,7 @@
 #include "llvm/Analysis/RegionInfo.h"
 #include "llvm/Analysis/ScalarEvolution.h"
 #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
+#include "llvm/Analysis/ScalarEvolutionDivision.h"
 #include "llvm/Analysis/ScopedNoAliasAA.h"
 #include "llvm/Analysis/StackLifetime.h"
 #include "llvm/Analysis/StackSafetyAnalysis.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 1b111dc20d35c..4b462b9c6845c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -518,6 +518,7 @@ FUNCTION_PASS("print<phi-values>", PhiValuesPrinterPass(errs()))
 FUNCTION_PASS("print<postdomtree>", PostDominatorTreePrinterPass(errs()))
 FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(errs()))
 FUNCTION_PASS("print<scalar-evolution>", ScalarEvolutionPrinterPass(errs()))
+FUNCTION_PASS("print<scev-division>", SCEVDivisionPrinterPass(errs()))
 FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(errs()))
 FUNCTION_PASS("print<uniformity>", UniformityInfoPrinterPass(errs()))
 FUNCTION_PASS("prof-inject", ProfileInjectorPass())
diff --git a/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll b/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll
new file mode 100644
index 0000000000000..02db29eee6a85
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll
@@ -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
+
+division:
+  %div = sdiv i8 %num, %step
+  br label %loop.latch
+
+loop.latch:
+  %i.inc = add nuw 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.header
+
+exit:
+  ret void
+}
+
+; for (i = 0; i < n; i++)
+;   div = (a + b) * i / a;
+;
+; FIXME: Both the quotient and the remainder can cause signed/unsigned wrap,
+; e.g., when %a + %b = 0 && %a != 0.
+define void @addrec_a_b(i8 %n, i8 %a, i8 %b) {
+; CHECK-LABEL: 'addrec_a_b'
+; CHECK-NEXT:  Instruction: %div = sdiv i8 %num, %step
+; CHECK-NEXT:    Numerator: {0,+,(%a + %b)}<nuw><nsw><%loop>
+; CHECK-NEXT:    Denominator: (%a + %b)
+; CHECK-NEXT:    Quotient: {0,+,1}<nuw><nsw><%loop>
+; CHECK-NEXT:    Remainder: 0
+;
+entry:
+  %guard = icmp sgt i8 %n, 0
+  %step = add nsw nuw i8 %a, %b
+  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
+}
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index 835092c468695..a1f188fbf8d69 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -39,6 +39,7 @@
     "Delinearization",
     "Loop Access Analysis",
     "Scalar Evolution Analysis",
+    "Scalar Evolution Division",
 }
 
 

>From 0cba51e420109a52e7af8a6716ed53183dfc4409 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Fri, 29 Aug 2025 00:32:44 +0900
Subject: [PATCH 2/3] Address review comments

---
 .../llvm/Analysis/ScalarEvolutionDivision.h   | 15 +++++-
 .../Analysis/ScalarEvolutionDivision/sdiv.ll  | 49 ++++---------------
 2 files changed, 23 insertions(+), 41 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
index cf6db50fddbe3..edd307dd6da13 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
@@ -25,8 +25,19 @@ struct SCEVCouldNotCompute;
 
 struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
 public:
-  // Computes the Quotient and Remainder of the division of Numerator by
-  // Denominator.
+  /// Computes the Quotient and Remainder of the division of Numerator by
+  /// Denominator. We are not actually performing the division here. Instead, we
+  /// are trying to find SCEV expressions Quotient and Remainder that satisfy:
+  ///
+  /// Numerator = Denominator * Quotient + Remainder
+  ///
+  /// There may be multiple valid answers for Quotient and Remainder. This
+  /// function finds one of them. Especially, there is always a trivial
+  /// solution: (Quotient, Remainder) = (0, Numerator).
+  ///
+  /// Note the following:
+  /// * The condition Remainder < Denominator is NOT necessarily required.
+  /// * Division of constants is performed as signed.
   static void divide(ScalarEvolution &SE, const SCEV *Numerator,
                      const SCEV *Denominator, const SCEV **Quotient,
                      const SCEV **Remainder);
diff --git a/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll b/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll
index 02db29eee6a85..e3cf15eb63534 100644
--- a/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll
+++ b/llvm/test/Analysis/ScalarEvolutionDivision/sdiv.ll
@@ -1,7 +1,7 @@
 ; 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) {
+define noundef i8 @add(i8 %x, i8 %y) {
 ; CHECK-LABEL: 'add'
 ; CHECK-NEXT:  Instruction: %div = sdiv i8 %add, %y
 ; CHECK-NEXT:    Numerator: (%x + %y)
@@ -14,24 +14,22 @@ define i8 @add(i8 %x, i8 %y) {
   ret i8 %div
 }
 
-define i8 @mul_add_mul(i8 %a, i8 %b, i8 %c) {
+define noundef 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:    Numerator: ((2 * %c)<nuw><nsw> + (%a * %b)<nuw><nsw>)<nuw><nsw>
 ; CHECK-NEXT:    Denominator: %a
 ; CHECK-NEXT:    Quotient: %b
-; CHECK-NEXT:    Remainder: (2 * %c)
+; CHECK-NEXT:    Remainder: (2 * %c)<nuw><nsw>
 ;
   %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
+  %mul1 = mul nsw nuw i8 %c, 2
+  %add = add nsw nuw i8 %mul0, %mul1
   %div = sdiv i8 %add, %a
   ret i8 %div
 }
 
-; FIXME: We need nsw on mul.
-define i8 @mul(i8 %x, i8 %y) {
+define noundef i8 @mul(i8 %x, i8 %y) {
 ; CHECK-LABEL: 'mul'
 ; CHECK-NEXT:  Instruction: %div = sdiv i8 %mul, %y
 ; CHECK-NEXT:    Numerator: (%x * %y)
@@ -44,40 +42,13 @@ define i8 @mul(i8 %x, i8 %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) {
+define noundef 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:    Numerator: ((%a + %b)<nuw><nsw> * (%a + %c)<nuw><nsw>)<nuw><nsw>
 ; CHECK-NEXT:    Denominator: %a
 ; CHECK-NEXT:    Quotient: 0
-; CHECK-NEXT:    Remainder: ((%a + %b) * (%a + %c))
+; CHECK-NEXT:    Remainder: ((%a + %b)<nuw><nsw> * (%a + %c)<nuw><nsw>)<nuw><nsw>
 ;
   %add0 = add nsw nuw i8 %a, %b
   %add1 = add nsw nuw i8 %a, %c

>From d278b986cbd2b25793c9597c7f2d840d3889ea56 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Fri, 29 Aug 2025 09:48:36 +0000
Subject: [PATCH 3/3] Revise comment

---
 llvm/include/llvm/Analysis/ScalarEvolutionDivision.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
index edd307dd6da13..7c78487fea8c0 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
@@ -38,6 +38,8 @@ struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
   /// Note the following:
   /// * The condition Remainder < Denominator is NOT necessarily required.
   /// * Division of constants is performed as signed.
+  /// * The multiplication of Quotient and Denominator may wrap.
+  /// * The addition of Quotient*Denominator and Remainder may wrap.
   static void divide(ScalarEvolution &SE, const SCEV *Numerator,
                      const SCEV *Denominator, const SCEV **Quotient,
                      const SCEV **Remainder);



More information about the llvm-commits mailing list