Ryotaro Kasuga a13e04a694
[LoopInterchange] Update UTC version (NFC) (#181988)
This is a follow-up PR to #181804. While working on the stacked PRs, I
encountered some noisy diffs in the CHECK lines that don't change the
meaning of the tests. To avoid such changes and make the review easier,
this patch updates the UTC version. It also renames some BBs to suppress
warnings emitted by UTC.
2026-02-18 20:09:38 +09:00

178 lines
8.2 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -aa-pipeline=basic-aa -passes=loop-interchange -cache-line-size=64 -verify-dom-info -verify-loop-info -verify-scev -verify-loop-lcssa -S | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
;; Test to make sure DA outputs the correction direction
;; vector [< =] hence the loopnest is interchanged.
;;
;; void test1(unsigned a[restrict N1][N2],
;; unsigned b[restrict N1][N2],
;; unsigned c[restrict N1][N2]) {
;; for (unsigned long i2 = 1; i2 < N2-1; i2++) {
;; for (unsigned long i1 = 1; i1 < N1-1; i1++) {
;; a[i1][i2+1] = b[i1][i2];
;; c[i1][i2] = a[i1][i2];
;; }
;; }
;; }
define void @test1(ptr noalias noundef %a, ptr noalias noundef %b, ptr noalias noundef %c) {
; CHECK-LABEL: define void @test1(
; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias noundef [[B:%.*]], ptr noalias noundef [[C:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[LOOP2_HEADER_PREHEADER:.*]]
; CHECK: [[LOOP1_HEADER_PREHEADER:.*]]:
; CHECK-NEXT: br label %[[LOOP1_HEADER:.*]]
; CHECK: [[LOOP1_HEADER]]:
; CHECK-NEXT: [[I2:%.*]] = phi i64 [ [[I2_INC:%.*]], %[[LOOP1_LATCH:.*]] ], [ 1, %[[LOOP1_HEADER_PREHEADER]] ]
; CHECK-NEXT: [[I2_ST:%.*]] = add i64 [[I2]], 1
; CHECK-NEXT: [[I2_LD:%.*]] = add i64 [[I2]], 0
; CHECK-NEXT: br label %[[LOOP2_HEADER_SPLIT1:.*]]
; CHECK: [[LOOP2_HEADER_PREHEADER]]:
; CHECK-NEXT: br label %[[LOOP2_HEADER:.*]]
; CHECK: [[LOOP2_HEADER]]:
; CHECK-NEXT: [[I1:%.*]] = phi i64 [ [[TMP0:%.*]], %[[LOOP2_HEADER_SPLIT:.*]] ], [ 1, %[[LOOP2_HEADER_PREHEADER]] ]
; CHECK-NEXT: br label %[[LOOP1_HEADER_PREHEADER]]
; CHECK: [[LOOP2_HEADER_SPLIT1]]:
; CHECK-NEXT: [[I1_ST:%.*]] = add i64 [[I1]], 0
; CHECK-NEXT: [[I1_LD:%.*]] = add i64 [[I1]], 0
; CHECK-NEXT: [[A_ST:%.*]] = getelementptr inbounds [64 x i32], ptr [[A]], i64 [[I1_ST]], i64 [[I2_ST]]
; CHECK-NEXT: [[A_LD:%.*]] = getelementptr inbounds [64 x i32], ptr [[A]], i64 [[I1_LD]], i64 [[I2_LD]]
; CHECK-NEXT: [[B_LD:%.*]] = getelementptr inbounds [64 x i32], ptr [[B]], i64 [[I1]], i64 [[I2]]
; CHECK-NEXT: [[C_ST:%.*]] = getelementptr inbounds [64 x i32], ptr [[C]], i64 [[I1]], i64 [[I2]]
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B_LD]], align 4
; CHECK-NEXT: store i32 [[B_VAL]], ptr [[A_ST]], align 4
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A_LD]], align 4
; CHECK-NEXT: store i32 [[A_VAL]], ptr [[C_ST]], align 4
; CHECK-NEXT: [[I1_INC:%.*]] = add nuw nsw i64 [[I1]], 1
; CHECK-NEXT: [[LOOP2_EXITCOND_NOT:%.*]] = icmp eq i64 [[I1_INC]], 63
; CHECK-NEXT: br label %[[LOOP1_LATCH]]
; CHECK: [[LOOP2_HEADER_SPLIT]]:
; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[I1]], 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 63
; CHECK-NEXT: br i1 [[TMP1]], label %[[EXIT:.*]], label %[[LOOP2_HEADER]]
; CHECK: [[LOOP1_LATCH]]:
; CHECK-NEXT: [[I2_INC]] = add nuw nsw i64 [[I2]], 1
; CHECK-NEXT: [[LOOP1_EXITCOND_NOT:%.*]] = icmp eq i64 [[I2_INC]], 63
; CHECK-NEXT: br i1 [[LOOP1_EXITCOND_NOT]], label %[[LOOP2_HEADER_SPLIT]], label %[[LOOP1_HEADER]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop1.header
loop1.header:
%i2 = phi i64 [ 1, %entry ], [ %i2.inc, %loop1.latch ]
%i2.st = add i64 %i2, 1
%i2.ld = add i64 %i2, 0
br label %loop2.header
loop2.header:
%i1 = phi i64 [ 1, %loop1.header ], [ %i1.inc, %loop2.header ]
%i1.st = add i64 %i1, 0
%i1.ld = add i64 %i1, 0
%a.st = getelementptr inbounds [64 x i32], ptr %a, i64 %i1.st, i64 %i2.st
%a.ld = getelementptr inbounds [64 x i32], ptr %a, i64 %i1.ld, i64 %i2.ld
%b.ld = getelementptr inbounds [64 x i32], ptr %b, i64 %i1, i64 %i2
%c.st = getelementptr inbounds [64 x i32], ptr %c, i64 %i1, i64 %i2
%b.val = load i32, ptr %b.ld, align 4
store i32 %b.val, ptr %a.st, align 4 ; (X) store to a[i1][i2+1]
%a.val = load i32, ptr %a.ld, align 4 ; (Y) load from a[i1][i2]
store i32 %a.val, ptr %c.st, align 4
%i1.inc = add nuw nsw i64 %i1, 1
%loop2.exitcond.not = icmp eq i64 %i1.inc, 63
br i1 %loop2.exitcond.not, label %loop1.latch, label %loop2.header
loop1.latch:
%i2.inc = add nuw nsw i64 %i2, 1
%loop1.exitcond.not = icmp eq i64 %i2.inc, 63
br i1 %loop1.exitcond.not, label %exit, label %loop1.header
exit:
ret void
}
;; Semantically equivalent to test1() with only the difference
;; of the order of a load and a store at (X) and (Y).
;;
;; Test to make sure DA outputs the correction direction
;; vector [< =] hence the loopnest is interchanged.
define void @test2(ptr noalias noundef %a, ptr noalias noundef %b, ptr noalias noundef %c) {
; CHECK-LABEL: define void @test2(
; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias noundef [[B:%.*]], ptr noalias noundef [[C:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[LOOP2_HEADER_PREHEADER:.*]]
; CHECK: [[LOOP1_HEADER_PREHEADER:.*]]:
; CHECK-NEXT: br label %[[LOOP1_HEADER:.*]]
; CHECK: [[LOOP1_HEADER]]:
; CHECK-NEXT: [[I2:%.*]] = phi i64 [ [[I2_INC:%.*]], %[[LOOP1_LATCH:.*]] ], [ 1, %[[LOOP1_HEADER_PREHEADER]] ]
; CHECK-NEXT: [[I2_ST:%.*]] = add i64 [[I2]], 1
; CHECK-NEXT: [[I2_LD:%.*]] = add i64 [[I2]], 0
; CHECK-NEXT: br label %[[LOOP2_HEADER_SPLIT1:.*]]
; CHECK: [[LOOP2_HEADER_PREHEADER]]:
; CHECK-NEXT: br label %[[LOOP2_HEADER:.*]]
; CHECK: [[LOOP2_HEADER]]:
; CHECK-NEXT: [[I1:%.*]] = phi i64 [ [[TMP0:%.*]], %[[LOOP2_HEADER_SPLIT:.*]] ], [ 1, %[[LOOP2_HEADER_PREHEADER]] ]
; CHECK-NEXT: br label %[[LOOP1_HEADER_PREHEADER]]
; CHECK: [[LOOP2_HEADER_SPLIT1]]:
; CHECK-NEXT: [[I1_ST:%.*]] = add i64 [[I1]], 0
; CHECK-NEXT: [[I1_LD:%.*]] = add i64 [[I1]], 0
; CHECK-NEXT: [[A_ST:%.*]] = getelementptr inbounds [64 x i32], ptr [[A]], i64 [[I1_ST]], i64 [[I2_ST]]
; CHECK-NEXT: [[A_LD:%.*]] = getelementptr inbounds [64 x i32], ptr [[A]], i64 [[I1_LD]], i64 [[I2_LD]]
; CHECK-NEXT: [[B_LD:%.*]] = getelementptr inbounds [64 x i32], ptr [[B]], i64 [[I1]], i64 [[I2]]
; CHECK-NEXT: [[C_ST:%.*]] = getelementptr inbounds [64 x i32], ptr [[C]], i64 [[I1]], i64 [[I2]]
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B_LD]], align 4
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A_LD]], align 4
; CHECK-NEXT: store i32 [[B_VAL]], ptr [[A_ST]], align 4
; CHECK-NEXT: store i32 [[A_VAL]], ptr [[C_ST]], align 4
; CHECK-NEXT: [[I1_INC:%.*]] = add nuw nsw i64 [[I1]], 1
; CHECK-NEXT: [[LOOP2_EXITCOND_NOT:%.*]] = icmp eq i64 [[I1_INC]], 63
; CHECK-NEXT: br label %[[LOOP1_LATCH]]
; CHECK: [[LOOP2_HEADER_SPLIT]]:
; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[I1]], 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 63
; CHECK-NEXT: br i1 [[TMP1]], label %[[EXIT:.*]], label %[[LOOP2_HEADER]]
; CHECK: [[LOOP1_LATCH]]:
; CHECK-NEXT: [[I2_INC]] = add nuw nsw i64 [[I2]], 1
; CHECK-NEXT: [[LOOP1_EXITCOND_NOT:%.*]] = icmp eq i64 [[I2_INC]], 63
; CHECK-NEXT: br i1 [[LOOP1_EXITCOND_NOT]], label %[[LOOP2_HEADER_SPLIT]], label %[[LOOP1_HEADER]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop1.header
loop1.header:
%i2 = phi i64 [ 1, %entry ], [ %i2.inc, %loop1.latch ]
%i2.st = add i64 %i2, 1
%i2.ld = add i64 %i2, 0
br label %loop2.header
loop2.header:
%i1 = phi i64 [ 1, %loop1.header ], [ %i1.inc, %loop2.header ]
%i1.st = add i64 %i1, 0
%i1.ld = add i64 %i1, 0
%a.st = getelementptr inbounds [64 x i32], ptr %a, i64 %i1.st, i64 %i2.st
%a.ld = getelementptr inbounds [64 x i32], ptr %a, i64 %i1.ld, i64 %i2.ld
%b.ld = getelementptr inbounds [64 x i32], ptr %b, i64 %i1, i64 %i2
%c.st = getelementptr inbounds [64 x i32], ptr %c, i64 %i1, i64 %i2
%b.val = load i32, ptr %b.ld, align 4
%a.val = load i32, ptr %a.ld, align 4 ; (Y) load from a[i1][i2]
store i32 %b.val, ptr %a.st, align 4 ; (X) store to a[i1][i2+1]
store i32 %a.val, ptr %c.st, align 4
%i1.inc = add nuw nsw i64 %i1, 1
%loop2.exitcond.not = icmp eq i64 %i1.inc, 63
br i1 %loop2.exitcond.not, label %loop1.latch, label %loop2.header
loop1.latch:
%i2.inc = add nuw nsw i64 %i2, 1
%loop1.exitcond.not = icmp eq i64 %i2.inc, 63
br i1 %loop1.exitcond.not, label %exit, label %loop1.header
exit:
ret void
}