[llvm] 45a2214 - [SCEV] Add tests for folding multiply/divide by constants.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 5 08:22:19 PDT 2025
Author: Florian Hahn
Date: 2025-09-05T16:21:57+01:00
New Revision: 45a22142fc77aabb10d056edc87ab8841a18e975
URL: https://github.com/llvm/llvm-project/commit/45a22142fc77aabb10d056edc87ab8841a18e975
DIFF: https://github.com/llvm/llvm-project/commit/45a22142fc77aabb10d056edc87ab8841a18e975.diff
LOG: [SCEV] Add tests for folding multiply/divide by constants.
Add extra test coverage for follow-up to
https://github.com/llvm/llvm-project/pull/156730.
Added:
llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll b/llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll
new file mode 100644
index 0000000000000..9f4360d2ae383
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll
@@ -0,0 +1,187 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s
+
+declare void @use(ptr)
+
+define void @udiv4_and_udiv2_mul_4(i1 %c, ptr %A) {
+; CHECK-LABEL: 'udiv4_and_udiv2_mul_4'
+; CHECK-NEXT: Classifying expressions for: @udiv4_and_udiv2_mul_4
+; CHECK-NEXT: %start = select i1 %c, i32 512, i32 0
+; CHECK-NEXT: --> %start U: [0,513) S: [0,513)
+; CHECK-NEXT: %div.2 = lshr i32 %start, 1
+; CHECK-NEXT: --> (%start /u 2) U: [0,257) S: [0,257)
+; CHECK-NEXT: %div.4 = lshr i32 %start, 2
+; CHECK-NEXT: --> (%start /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %iv.start = zext i32 %div.4 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %wide.trip.count = zext i32 %div.2 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 2) U: [0,257) S: [0,257)
+; CHECK-NEXT: %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT: --> {((zext i32 %start to i64) /u 4),+,1}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) /u 2) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %gep = getelementptr i32, ptr %A, i64 %iv
+; CHECK-NEXT: --> {((zext i32 %start to i64) + %A),+,4}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) + (4 * ((zext i32 %start to i64) /u 2))<nuw><nsw> + (-4 * ((zext i32 %start to i64) /u 4))<nsw> + %A) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %iv.next = add i64 %iv, 1
+; CHECK-NEXT: --> {(1 + ((zext i32 %start to i64) /u 4))<nuw><nsw>,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((zext i32 %start to i64) /u 2))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @udiv4_and_udiv2_mul_4
+; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i64 -1
+; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: Trip multiple is 1
+;
+entry:
+ %start = select i1 %c, i32 512, i32 0
+ %div.2 = lshr i32 %start, 1
+ %div.4 = lshr i32 %start, 2
+ %iv.start = zext i32 %div.4 to i64
+ %wide.trip.count = zext i32 %div.2 to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr i32, ptr %A, i64 %iv
+ call void @use(ptr %gep)
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv, %wide.trip.count
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @udiv4_and_udiv2_mul_1(i1 %c, ptr %A) {
+; CHECK-LABEL: 'udiv4_and_udiv2_mul_1'
+; CHECK-NEXT: Classifying expressions for: @udiv4_and_udiv2_mul_1
+; CHECK-NEXT: %start = select i1 %c, i32 512, i32 0
+; CHECK-NEXT: --> %start U: [0,513) S: [0,513)
+; CHECK-NEXT: %div.2 = lshr i32 %start, 1
+; CHECK-NEXT: --> (%start /u 2) U: [0,257) S: [0,257)
+; CHECK-NEXT: %div.4 = lshr i32 %start, 2
+; CHECK-NEXT: --> (%start /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %iv.start = zext i32 %div.4 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %wide.trip.count = zext i32 %div.2 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 2) U: [0,257) S: [0,257)
+; CHECK-NEXT: %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT: --> {((zext i32 %start to i64) /u 4),+,1}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) /u 2) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %gep = getelementptr i8, ptr %A, i64 %iv
+; CHECK-NEXT: --> {(((zext i32 %start to i64) /u 4) + %A),+,1}<%loop> U: full-set S: full-set Exits: (((zext i32 %start to i64) /u 2) + %A) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %iv.next = add i64 %iv, 1
+; CHECK-NEXT: --> {(1 + ((zext i32 %start to i64) /u 4))<nuw><nsw>,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((zext i32 %start to i64) /u 2))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @udiv4_and_udiv2_mul_1
+; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i64 -1
+; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: Trip multiple is 1
+;
+entry:
+ %start = select i1 %c, i32 512, i32 0
+ %div.2 = lshr i32 %start, 1
+ %div.4 = lshr i32 %start, 2
+ %iv.start = zext i32 %div.4 to i64
+ %wide.trip.count = zext i32 %div.2 to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr i8, ptr %A, i64 %iv
+ call void @use(ptr %gep)
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv, %wide.trip.count
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+
+define void @udiv3_and_udiv5_mul_4(i1 %c, ptr %A) {
+; CHECK-LABEL: 'udiv3_and_udiv5_mul_4'
+; CHECK-NEXT: Classifying expressions for: @udiv3_and_udiv5_mul_4
+; CHECK-NEXT: %start = select i1 %c, i32 512, i32 0
+; CHECK-NEXT: --> %start U: [0,513) S: [0,513)
+; CHECK-NEXT: %div.3 = udiv i32 %start, 3
+; CHECK-NEXT: --> (%start /u 3) U: [0,171) S: [0,171)
+; CHECK-NEXT: %div.5 = udiv i32 %start, 5
+; CHECK-NEXT: --> (%start /u 5) U: [0,103) S: [0,103)
+; CHECK-NEXT: %iv.start = zext i32 %div.5 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 5) U: [0,103) S: [0,103)
+; CHECK-NEXT: %wide.trip.count = zext i32 %div.3 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 3) U: [0,171) S: [0,171)
+; CHECK-NEXT: %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT: --> {((zext i32 %start to i64) /u 5),+,1}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) /u 3) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %gep = getelementptr i8, ptr %A, i64 %iv
+; CHECK-NEXT: --> {(((zext i32 %start to i64) /u 5) + %A),+,1}<%loop> U: full-set S: full-set Exits: (((zext i32 %start to i64) /u 3) + %A) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %iv.next = add i64 %iv, 1
+; CHECK-NEXT: --> {(1 + ((zext i32 %start to i64) /u 5))<nuw><nsw>,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((zext i32 %start to i64) /u 3))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @udiv3_and_udiv5_mul_4
+; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 5))<nsw> + ((zext i32 %start to i64) /u 3))
+; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i64 -1
+; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 5))<nsw> + ((zext i32 %start to i64) /u 3))
+; CHECK-NEXT: Loop %loop: Trip multiple is 1
+;
+entry:
+ %start = select i1 %c, i32 512, i32 0
+ %div.3 = udiv i32 %start, 3
+ %div.5 = udiv i32 %start, 5
+ %iv.start = zext i32 %div.5 to i64
+ %wide.trip.count = zext i32 %div.3 to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr i8, ptr %A, i64 %iv
+ call void @use(ptr %gep)
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv, %wide.trip.count
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @udiv4_and_udiv2_mul_4_dividend_multiple_of_2(i1 %c, ptr %A) {
+; CHECK-LABEL: 'udiv4_and_udiv2_mul_4_dividend_multiple_of_2'
+; CHECK-NEXT: Classifying expressions for: @udiv4_and_udiv2_mul_4_dividend_multiple_of_2
+; CHECK-NEXT: %start = select i1 %c, i32 514, i32 0
+; CHECK-NEXT: --> %start U: [0,515) S: [0,515)
+; CHECK-NEXT: %div.2 = lshr i32 %start, 1
+; CHECK-NEXT: --> (%start /u 2) U: [0,258) S: [0,258)
+; CHECK-NEXT: %div.4 = lshr i32 %start, 2
+; CHECK-NEXT: --> (%start /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %iv.start = zext i32 %div.4 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 4) U: [0,129) S: [0,129)
+; CHECK-NEXT: %wide.trip.count = zext i32 %div.2 to i64
+; CHECK-NEXT: --> ((zext i32 %start to i64) /u 2) U: [0,258) S: [0,258)
+; CHECK-NEXT: %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT: --> {((zext i32 %start to i64) /u 4),+,1}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) /u 2) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %gep = getelementptr i32, ptr %A, i64 %iv
+; CHECK-NEXT: --> {((4 * ((zext i32 %start to i64) /u 4))<nuw><nsw> + %A),+,4}<%loop> U: full-set S: full-set Exits: ((4 * ((zext i32 %start to i64) /u 2))<nuw><nsw> + %A) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: %iv.next = add i64 %iv, 1
+; CHECK-NEXT: --> {(1 + ((zext i32 %start to i64) /u 4))<nuw><nsw>,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((zext i32 %start to i64) /u 2))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @udiv4_and_udiv2_mul_4_dividend_multiple_of_2
+; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i64 -1
+; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * ((zext i32 %start to i64) /u 4))<nsw> + ((zext i32 %start to i64) /u 2))
+; CHECK-NEXT: Loop %loop: Trip multiple is 1
+;
+entry:
+ %start = select i1 %c, i32 514, i32 0
+ %div.2 = lshr i32 %start, 1
+ %div.4 = lshr i32 %start, 2
+ %iv.start = zext i32 %div.4 to i64
+ %wide.trip.count = zext i32 %div.2 to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %iv.start, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr i32, ptr %A, i64 %iv
+ call void @use(ptr %gep)
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv, %wide.trip.count
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+
More information about the llvm-commits
mailing list