[llvm] [SCEV] Complete instr-types in CanConstantFold (PR #218874)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 03:02:45 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Ramkumar Ramachandra (artagnon)

<details>
<summary>Changes</summary>

Match the types in the ConstantFolder. This allows us to compute more trip counts.

Assisted-by: AI, for test cases

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


2 Files Affected:

- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+3-3) 
- (modified) llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll (+102) 


``````````diff
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index f6ad701ce819e..7874bd7ca4b53 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9741,9 +9741,9 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
 /// Return true if we can constant fold an instruction of the specified type,
 /// assuming that all operands were constants.
 static bool CanConstantFold(const Instruction *I) {
-  if (isa<BinaryOperator>(I) || isa<CmpInst>(I) ||
-      isa<SelectInst>(I) || isa<CastInst>(I) || isa<GetElementPtrInst>(I) ||
-      isa<LoadInst>(I) || isa<ExtractValueInst>(I))
+  if (isa<BinaryOperator, UnaryOperator, GEPOperator, FreezeInst, CmpInst,
+          SelectInst, CastInst, LoadInst, ExtractElementInst, InsertElementInst,
+          ExtractValueInst, InsertValueInst>(I))
     return true;
 
   if (const CallInst *CI = dyn_cast<CallInst>(I))
diff --git a/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll b/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll
index cc08fa5fc7d87..4fc7fc1f530a3 100644
--- a/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll
@@ -177,6 +177,108 @@ exit:
   ret i64 %iv
 }
 
+define i64 @test_fneg() {
+; CHECK-LABEL: 'test_fneg'
+; CHECK-NEXT:  Determining loop execution counts for: @test_fneg
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i32 7
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 7
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i32 7
+; CHECK-NEXT:  Loop %loop: Trip multiple is 8
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ]
+  call void @use(double %fv)
+  %fv.neg = fneg double %fv
+  %fv.next = fsub double %fv, %fv.neg
+  %iv.next = add i64 %iv, 1
+  %fcmp = fcmp une double %fv, 128.0
+  br i1 %fcmp, label %loop, label %exit
+
+exit:
+  ret i64 %iv
+}
+
+define i64 @test_freeze() {
+; CHECK-LABEL: 'test_freeze'
+; CHECK-NEXT:  Determining loop execution counts for: @test_freeze
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i32 5
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 5
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i32 5
+; CHECK-NEXT:  Loop %loop: Trip multiple is 6
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  call void @dummy()
+  %iv.next = add i64 %iv, 1
+  %iv.fr = freeze i64 %iv
+  %icmp = icmp ne i64 %iv.fr, 5
+  br i1 %icmp, label %loop, label %exit
+
+exit:
+  ret i64 %iv
+}
+
+define i64 @test_extract_insert_element() {
+; CHECK-LABEL: 'test_extract_insert_element'
+; CHECK-NEXT:  Determining loop execution counts for: @test_extract_insert_element
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: Trip multiple is 5
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %vec = phi <2 x i64> [ <i64 0, i64 3>, %entry ], [ %vec.next, %loop ]
+  call void @use.v2i64(<2 x i64> %vec)
+  %el = extractelement <2 x i64> %vec, i32 0
+  %el.next = add i64 %el, 1
+  %vec.next = insertelement <2 x i64> %vec, i64 %el.next, i32 0
+  %iv.next = add i64 %iv, 1
+  %icmp = icmp ne i64 %el, 4
+  br i1 %icmp, label %loop, label %exit
+
+exit:
+  ret i64 %iv
+}
+
+define i64 @test_extract_insert_value() {
+; CHECK-LABEL: 'test_extract_insert_value'
+; CHECK-NEXT:  Determining loop execution counts for: @test_extract_insert_value
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i32 4
+; CHECK-NEXT:  Loop %loop: Trip multiple is 5
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %agg = phi { i64, i32 } [ { i64 0, i32 3 }, %entry ], [ %agg.next, %loop ]
+  call void @use.agg({ i64, i32 } %agg)
+  %fld = extractvalue { i64, i32 } %agg, 0
+  %fld.next = add i64 %fld, 1
+  %agg.next = insertvalue { i64, i32 } %agg, i64 %fld.next, 0
+  %iv.next = add i64 %iv, 1
+  %icmp = icmp ne i64 %fld, 4
+  br i1 %icmp, label %loop, label %exit
+
+exit:
+  ret i64 %iv
+}
+
 declare void @dummy()
 declare void @use(double %i)
+declare void @use.v2i64(<2 x i64>)
+declare void @use.agg({ i64, i32 })
 declare double @llvm.sin.f64(double)

``````````

</details>


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


More information about the llvm-commits mailing list