[llvm] [DA] Add tests for GCD MIV misses dependency due to overflow (PR #169926)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 28 17:31:08 PST 2025


================
@@ -56,6 +56,125 @@ loop:
   %ec = icmp eq i64 %i.inc, 100
   br i1 %ec, label %exit, label %loop
 
+exit:
+  ret void
+}
+
+; max_i = INT64_MAX/6  // 1537228672809129301
+; for (long long i = 0; i <= max_i; i++) {
+;   A[-6*i + INT64_MAX] = 0;
+;   if (i)
+;     A[3*i - 2] = 1;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. For example,
+;
+;  memory access       | i == 1 | i == (max_i + 1) / 2 | i == max_i
+; ---------------------|--------|----------------------|-------------------
+;  A[-6*i + INT64_MAX] |        | A[3*max_i - 2]       | A[1]
+;  A[3*i - 2]          | A[1]   |                      | A[3*max_i - 2]
+;
+;
+define void @gcdmiv_delta_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'gcdmiv_delta_ovfl'
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+;
+; CHECK-GCD-MIV-LABEL: 'gcdmiv_delta_ovfl'
+; CHECK-GCD-MIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - consistent output [*]!
+; CHECK-GCD-MIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - none!
+; CHECK-GCD-MIV-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - consistent output [*]!
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+  %subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop.latch ]
+  %subscript.1 = phi i64 [ -2, %entry ], [ %subscript.1.next, %loop.latch ]
+  %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
+  store i8 0, ptr %idx.0
+  %cond.store = icmp ne i64 %i, 0
+  br i1 %cond.store, label %if.store, label %loop.latch
+
+if.store:
+  %idx.1 = getelementptr i8, ptr %A, i64 %subscript.1
+  store i8 1, ptr %idx.1
+  br label %loop.latch
+
+loop.latch:
+  %i.inc = add nuw nsw i64 %i, 1
+  %subscript.0.next = add nsw i64 %subscript.0, -6
+  %subscript.1.next = add nsw i64 %subscript.1, 3
+  %exitcond = icmp sgt i64 %i.inc, 1537228672809129301
+  br i1 %exitcond, label %exit, label %loop.header
+
+exit:
+  ret void
+}
+
+; max_i = INT64_MAX/3  // 3074457345618258602
+; for (i = 0; i < max_i; i++) {
+;   A[3*i] = 0;
+;   A[-3*i - 3*m - INT64_MAX] = 1;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it may exist. For example, consider `m = 1`. Then,
+; `-3*m - INT64_MAX` is `INT64_MAX - 1`. So `-3*i - 3*m - INT64_MAX` is
+; effectively `-3*i + (INT64_MAX - 1)`. Thus, accesses will be as follows:
+;
+;  memory access             | i == 1           | i == max_i - 1
+; ---------------------------|------------------|------------------
+;  A[3*i]                    | A[3]             | A[INT64_MAX - 4]
+;  A[-3*i - 3*m - INT64_MAX] | A[INT64_MAX - 4] | A[3]
+;
+
+define void @gcdmiv_const_ovfl(ptr %A, i64 %m) {
+; CHECK-ALL-LABEL: 'gcdmiv_const_ovfl'
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:  Src: store i8 1, ptr %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+;
+; CHECK-GCD-MIV-LABEL: 'gcdmiv_const_ovfl'
+; CHECK-GCD-MIV-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - consistent output [*]!
+; CHECK-GCD-MIV-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - none!
+; CHECK-GCD-MIV-NEXT:  Src: store i8 1, ptr %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
+; CHECK-GCD-MIV-NEXT:    da analyze - consistent output [*]!
+;
+entry:
+  %m.3 = mul nsw i64 -3, %m
+  %const = sub i64 %m.3, 9223372036854775807
+  %guard = icmp ne i64 %const, 0
+  br i1 %guard, label %loop, label %exit
----------------
kasuga-fj wrote:

This is a hack to transfer the `nsw` flag of `3 * %m` from IR to SCEV. Please let me know if there is a better way to do this.

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


More information about the llvm-commits mailing list