[llvm-branch-commits] [NFCI] [ValueTracking] Add pass to print ConstantRanges (PR #140144)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu May 15 14:38:49 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-testing-tools

Author: Florian Mayer (fmayer)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/140144.diff


6 Files Affected:

- (modified) llvm/include/llvm/Analysis/ValueTracking.h (+15-1) 
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+17) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1) 
- (modified) llvm/lib/Passes/PassRegistry.def (+1) 
- (added) llvm/test/Analysis/ValueTracking/print-constant-range.ll (+234) 
- (modified) llvm/utils/UpdateTestChecks/common.py (+1) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 61dbb07e7128e..341c20931761a 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -19,9 +19,10 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/FMF.h"
-#include "llvm/IR/Instructions.h"
 #include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/PassManager.h"
 #include <cassert>
 #include <cstdint>
 
@@ -1001,6 +1002,19 @@ std::optional<bool> isImpliedByDomCondition(CmpPredicate Pred, const Value *LHS,
 void findValuesAffectedByCondition(Value *Cond, bool IsAssume,
                                    function_ref<void(Value *)> InsertAffected);
 
+/// Printer pass for \p computeConstantRange results.
+class ConstantRangePrinterPass
+    : public PassInfoMixin<ConstantRangePrinterPass> {
+  raw_ostream &OS;
+
+public:
+  explicit ConstantRangePrinterPass(raw_ostream &OS) : OS(OS) {}
+
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+  static bool isRequired() { return true; }
+};
+
 } // end namespace llvm
 
 #endif // LLVM_ANALYSIS_VALUETRACKING_H
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 3d403531cea2f..3ebbf887b3e6c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -49,6 +49,7 @@
 #include "llvm/IR/GlobalAlias.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -10451,3 +10452,19 @@ void llvm::findValuesAffectedByCondition(
     }
   }
 }
+
+PreservedAnalyses ConstantRangePrinterPass::run(Function &F,
+                                                FunctionAnalysisManager &AM) {
+  // For compatibility with opt's -analyze feature under legacy pass manager
+  // which was not ported to NPM. This keeps tests using
+  // update_analyze_test_checks.py working.
+  OS << "Printing analysis 'ConstantRange' for function '" << F.getName()
+     << "':\n";
+  for (const Instruction &I : instructions(F)) {
+    if (!I.getType()->isIntOrIntVectorTy())
+      continue;
+    auto CR = computeConstantRange(&I, false);
+    OS << I << ": " << CR << "\n";
+  }
+  return PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 7740f622ede7c..060c1b535befd 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -78,6 +78,7 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
 #include "llvm/Analysis/UniformityAnalysis.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/CodeGen/AssignmentTrackingAnalysis.h"
 #include "llvm/CodeGen/AtomicExpand.h"
 #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index ea792280ed975..8cbc6a1156c51 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -462,6 +462,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<constant-range>", ConstantRangePrinterPass(errs()))
 FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(errs()))
 FUNCTION_PASS("print<uniformity>", UniformityInfoPrinterPass(errs()))
 FUNCTION_PASS("reassociate", ReassociatePass())
diff --git a/llvm/test/Analysis/ValueTracking/print-constant-range.ll b/llvm/test/Analysis/ValueTracking/print-constant-range.ll
new file mode 100644
index 0000000000000..ad444551e9adc
--- /dev/null
+++ b/llvm/test/Analysis/ValueTracking/print-constant-range.ll
@@ -0,0 +1,234 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -disable-output '-passes=print<constant-range>' < %s -S 2>&1 | FileCheck %s
+
+define i1 @shl_C_X_ugt(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt'
+; CHECK-NEXT:    %shl = shl i8 7, %x: [1,-31)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -32: full-set
+;
+  %shl = shl i8 7, %x
+  %r = icmp ugt i8 %shl, 224
+  ret i1 %r
+}
+
+define i1 @shl_C_X_ugt2(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt2'
+; CHECK-NEXT:    %shl = shl i8 5, %x: [1,-63)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -64: full-set
+;
+  %shl = shl i8 5, %x
+  %r = icmp ugt i8 %shl, 192
+  ret i1 %r
+}
+
+define i1 @shl_C_X_ugt_fail(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt_fail'
+; CHECK-NEXT:    %shl = shl i8 1, %x: [1,-127)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, 127: full-set
+;
+  %shl = shl i8 1, %x
+  %r = icmp ugt i8 %shl, 127
+  ret i1 %r
+}
+
+define i1 @shl_C_X_ugt_fail2(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt_fail2'
+; CHECK-NEXT:    %shl = shl i8 3, %x: [1,-63)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -66: full-set
+;
+  %shl = shl i8 3, %x
+  %r = icmp ugt i8 %shl, 190
+  ret i1 %r
+}
+
+define i1 @shl_C_X_ugt_fail3(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt_fail3'
+; CHECK-NEXT:    %shl = shl i8 -1, %x: [1,0)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -2: full-set
+;
+  %shl = shl i8 -1, %x
+  %r = icmp ugt i8 %shl, 254
+  ret i1 %r
+}
+
+define i1 @shl_C_X_ugt_todo(i8 %x) {
+; CHECK-LABEL: 'shl_C_X_ugt_todo'
+; CHECK-NEXT:    %shl = shl i8 -127, %x: [1,-63)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -116: full-set
+;
+  %shl = shl i8 129, %x
+  %r = icmp ugt i8 %shl, 140
+  ret i1 %r
+}
+
+define i1 @shl_X_C_ugt(i8 %x) {
+; CHECK-LABEL: 'shl_X_C_ugt'
+; CHECK-NEXT:    %shl = shl i8 %x, 6: [0,-63)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -64: full-set
+;
+  %shl = shl i8 %x, 6
+  %r = icmp ugt i8 %shl, 192
+  ret i1 %r
+}
+
+define i1 @shl_X_C_ugt_fail(i8 %x) {
+; CHECK-LABEL: 'shl_X_C_ugt_fail'
+; CHECK-NEXT:    %shl = shl i8 %x, 6: [0,-63)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -65: full-set
+;
+  %shl = shl i8 %x, 6
+  %r = icmp ugt i8 %shl, 191
+  ret i1 %r
+}
+
+define i1 @shl_X_C_ugt_fail2(i8 %x) {
+; CHECK-LABEL: 'shl_X_C_ugt_fail2'
+; CHECK-NEXT:    %shl = shl i8 %x, 5: [0,-31)
+; CHECK-NEXT:    %r = icmp ugt i8 %shl, -64: full-set
+;
+  %shl = shl i8 %x, 5
+  %r = icmp ugt i8 %shl, 192
+  ret i1 %r
+}
+
+define i1 @and_ugt(i8 %xx) {
+; CHECK-LABEL: 'and_ugt'
+; CHECK-NEXT:    %x = mul i8 %xx, %xx: full-set
+; CHECK-NEXT:    %negx = sub i8 0, %x: full-set
+; CHECK-NEXT:    %x_p2 = and i8 %negx, %x: [0,-127)
+; CHECK-NEXT:    %r = icmp ugt i8 %x_p2, -128: full-set
+;
+  %x = mul i8 %xx, %xx  ; thwart complexity-based canonicalization
+  %negx = sub i8 0, %x
+  %x_p2 = and i8 %negx, %x
+  %r = icmp ugt i8 %x_p2, 128
+  ret i1 %r
+}
+
+define i1 @and_ugt2(i8 %xx) {
+; CHECK-LABEL: 'and_ugt2'
+; CHECK-NEXT:    %x = mul i8 %xx, %xx: full-set
+; CHECK-NEXT:    %negx = sub i8 0, %x: full-set
+; CHECK-NEXT:    %x_p2 = and i8 %x, %negx: [0,-127)
+; CHECK-NEXT:    %r = icmp ugt i8 %x_p2, -128: full-set
+;
+  %x = mul i8 %xx, %xx  ; thwart complexity-based canonicalization
+  %negx = sub i8 0, %x
+  %x_p2 = and i8 %x, %negx
+  %r = icmp ugt i8 %x_p2, 128
+  ret i1 %r
+}
+
+define i1 @and_ugt_fail(i8 %xx) {
+; CHECK-LABEL: 'and_ugt_fail'
+; CHECK-NEXT:    %x = mul i8 %xx, %xx: full-set
+; CHECK-NEXT:    %negx = sub i8 0, %x: full-set
+; CHECK-NEXT:    %x_p2 = and i8 %x, %negx: [0,-127)
+; CHECK-NEXT:    %r = icmp ugt i8 %x_p2, 127: full-set
+;
+  %x = mul i8 %xx, %xx  ; thwart complexity-based canonicalization
+  %negx = sub i8 0, %x
+  %x_p2 = and i8 %x, %negx
+  %r = icmp ugt i8 %x_p2, 127
+  ret i1 %r
+}
+
+define i1 @urem_okay(i8 %x) {
+; CHECK-LABEL: 'urem_okay'
+; CHECK-NEXT:    %val = urem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp ule i8 %val, 35: full-set
+;
+  %val = urem i8 34, %x
+  %r = icmp ule i8 %val, 35
+  ret i1 %r
+}
+
+define i1 @urem_fail(i8 %x) {
+; CHECK-LABEL: 'urem_fail'
+; CHECK-NEXT:    %val = urem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp ule i8 %val, 33: full-set
+;
+  %val = urem i8 34, %x
+  %r = icmp ule i8 %val, 33
+  ret i1 %r
+}
+
+define i1 @srem_posC_okay0(i8 %x) {
+; CHECK-LABEL: 'srem_posC_okay0'
+; CHECK-NEXT:    %val = srem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp sle i8 %val, 34: full-set
+;
+  %val = srem i8 34, %x
+  %r = icmp sle i8 %val, 34
+  ret i1 %r
+}
+
+define i1 @srem_posC_okay1(i8 %x) {
+; CHECK-LABEL: 'srem_posC_okay1'
+; CHECK-NEXT:    %val = srem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp sge i8 %val, -3: full-set
+;
+  %val = srem i8 34, %x
+  %r = icmp sge i8 %val, -3
+  ret i1 %r
+}
+
+define i1 @srem_negC_okay0(i8 %x) {
+; CHECK-LABEL: 'srem_negC_okay0'
+; CHECK-NEXT:    %val = srem i8 -34, %x: [-34,1)
+; CHECK-NEXT:    %r = icmp sle i8 %val, 0: full-set
+;
+  %val = srem i8 -34, %x
+  %r = icmp sle i8 %val, 0
+  ret i1 %r
+}
+
+define i1 @srem_negC_okay1(i8 %x) {
+; CHECK-LABEL: 'srem_negC_okay1'
+; CHECK-NEXT:    %val = srem i8 -34, %x: [-34,1)
+; CHECK-NEXT:    %r = icmp sge i8 %val, -34: full-set
+;
+  %val = srem i8 -34, %x
+  %r = icmp sge i8 %val, -34
+  ret i1 %r
+}
+
+define i1 @srem_posC_fail0(i8 %x) {
+; CHECK-LABEL: 'srem_posC_fail0'
+; CHECK-NEXT:    %val = srem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp sle i8 %val, 32: full-set
+;
+  %val = srem i8 34, %x
+  %r = icmp sle i8 %val, 32
+  ret i1 %r
+}
+
+define i1 @srem_posC_fail1(i8 %x) {
+; CHECK-LABEL: 'srem_posC_fail1'
+; CHECK-NEXT:    %val = srem i8 34, %x: [0,35)
+; CHECK-NEXT:    %r = icmp sge i8 %val, 1: full-set
+;
+  %val = srem i8 34, %x
+  %r = icmp sge i8 %val, 1
+  ret i1 %r
+}
+
+define i1 @srem_negC_fail0(i8 %x) {
+; CHECK-LABEL: 'srem_negC_fail0'
+; CHECK-NEXT:    %val = srem i8 -34, %x: [-34,1)
+; CHECK-NEXT:    %r = icmp sle i8 %val, -1: full-set
+;
+  %val = srem i8 -34, %x
+  %r = icmp sle i8 %val, -1
+  ret i1 %r
+}
+
+define i1 @srem_negC_fail1(i8 %x) {
+; CHECK-LABEL: 'srem_negC_fail1'
+; CHECK-NEXT:    %val = srem i8 -34, %x: [-34,1)
+; CHECK-NEXT:    %r = icmp sge i8 %val, -33: full-set
+;
+  %val = srem i8 -34, %x
+  %r = icmp sge i8 %val, -33
+  ret i1 %r
+}
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index d150612dd368e..5d57536b010b6 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -38,6 +38,7 @@
     "Dependence Analysis",
     "Loop Access Analysis",
     "Scalar Evolution Analysis",
+    "ConstantRange",
 }
 
 

``````````

</details>


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


More information about the llvm-branch-commits mailing list