Files
Ryotaro Kasuga 641c32e053 [LoopInterchange] Fix test phi-ordering.ll (NFC) (#181989)
I found that the test phi-ordering.ll is a bit fragile and can fail with
any irrelevant changes. Also this test is not consistent with the
following comment, which is at the top of the file:

```
;; Checks the order of the inner phi nodes does not cause havoc.
;; The inner loop has a reduction into c. The IV is not the first phi.
```

After examining the change history, I found that the original intent of
this test was effectively lost in
c8bd6ea35e.
A workaround was introduced later in
eac3487510
to preserve the test output, but this seems to have made the test more
complicated.

This patch updates the test so that its original intent is restored. The
change is close to a partial revert of
c8bd6ea35e.
Even though the feature for inner-only reductions has been removed, I
believe it is still better to keep the test as it is, otherwise the test
would be meaningless.
2026-02-25 11:07:37 +00:00

99 lines
4.5 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -verify-dom-info -verify-loop-info -verify-scev -verify-loop-lcssa -loop-interchange-threshold=0 -S 2>&1 | FileCheck %s
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
; Checks the order of the inner phi nodes does not cause havoc.
; The inner loop has a reduction into C. The IV is not the first phi.
;
; for (i = 0; i < 90; i++)
; for (j = 0; j < 90; j++) {
; red = C[i][j];
; for (k = 1; k < 90; k++) {
; red += A[i][k];
; }
; C[i][j] = red;
; }
; Function Attrs: norecurse nounwind
define void @test(i32 %T, ptr noalias nocapture %C, ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B) local_unnamed_addr #0 {
; CHECK-LABEL: define void @test(
; CHECK-SAME: i32 [[T:%.*]], ptr noalias captures(none) [[C:%.*]], ptr noalias readonly captures(none) [[A:%.*]], ptr noalias readonly captures(none) [[B:%.*]]) local_unnamed_addr {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[FOR1_HEADER:.*]]
; CHECK: [[FOR1_HEADER]]:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC20:%.*]], %[[FOR1_INC19:.*]] ], [ 0, %[[ENTRY]] ]
; CHECK-NEXT: br label %[[FOR2_HEADER:.*]]
; CHECK: [[FOR2_HEADER]]:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[FOR1_HEADER]] ], [ [[INC17:%.*]], %[[FOR2_INC16:.*]] ]
; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds [90 x i32], ptr [[C]], i32 [[I]], i32 [[J]]
; CHECK-NEXT: [[RED_INIT:%.*]] = load i32, ptr [[GEP_C]], align 4
; CHECK-NEXT: br label %[[FOR3:.*]]
; CHECK: [[FOR3]]:
; CHECK-NEXT: [[RED:%.*]] = phi i32 [ [[RED_INIT]], %[[FOR2_HEADER]] ], [ [[ADD15:%.*]], %[[FOR3]] ]
; CHECK-NEXT: [[K:%.*]] = phi i32 [ 1, %[[FOR2_HEADER]] ], [ [[INC:%.*]], %[[FOR3]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [90 x i16], ptr [[A]], i32 [[I]], i32 [[K]]
; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT: [[ADD15]] = add nsw i32 [[CONV]], [[RED]]
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[K]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 90
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR2_INC16]], label %[[FOR3]]
; CHECK: [[FOR2_INC16]]:
; CHECK-NEXT: [[RED_LCSSA:%.*]] = phi i32 [ [[RED]], %[[FOR3]] ]
; CHECK-NEXT: store i32 [[RED_LCSSA]], ptr [[GEP_C]], align 4
; CHECK-NEXT: [[INC17]] = add nuw nsw i32 [[J]], 1
; CHECK-NEXT: [[EXITCOND47:%.*]] = icmp eq i32 [[INC17]], 90
; CHECK-NEXT: br i1 [[EXITCOND47]], label %[[FOR1_INC19]], label %[[FOR2_HEADER]]
; CHECK: [[FOR1_INC19]]:
; CHECK-NEXT: [[INC20]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[EXITCOND48:%.*]] = icmp eq i32 [[INC20]], 90
; CHECK-NEXT: br i1 [[EXITCOND48]], label %[[FOR1_LOOPEXIT:.*]], label %[[FOR1_HEADER]]
; CHECK: [[FOR1_LOOPEXIT]]:
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %for1.header
for1.header: ; preds = %entry
%i = phi i32 [ %inc20, %for1.inc19 ], [ 0, %entry ]
br label %for2.header
for2.header: ; preds = %for2.inc16, %for1.header
%j = phi i32 [ 0, %for1.header ], [ %inc17, %for2.inc16 ]
%gep.c = getelementptr inbounds [90 x i32], ptr %C, i32 %i, i32 %j
%red.init = load i32, ptr %gep.c
br label %for3
for3: ; preds = %for3, %for2.header
%red = phi i32 [ %red.init, %for2.header ], [ %add15, %for3 ]
%k = phi i32 [ 1, %for2.header ], [ %inc, %for3 ]
%arrayidx = getelementptr inbounds [90 x i16], ptr %A, i32 %i, i32 %k
%0 = load i16, ptr %arrayidx, align 2
%conv = sext i16 %0 to i32
%add15 = add nsw i32 %conv, %red
%inc = add nuw nsw i32 %k, 1
%exitcond = icmp eq i32 %inc, 90
br i1 %exitcond, label %for2.inc16, label %for3
for2.inc16: ; preds = %for.body6
%red.lcssa = phi i32 [ %red, %for3 ]
store i32 %red.lcssa, ptr %gep.c
%inc17 = add nuw nsw i32 %j, 1
%exitcond47 = icmp eq i32 %inc17, 90
br i1 %exitcond47, label %for1.inc19, label %for2.header
for1.inc19: ; preds = %for2.inc16
%inc20 = add nuw nsw i32 %i, 1
%exitcond48 = icmp eq i32 %inc20, 90
br i1 %exitcond48, label %for1.loopexit, label %for1.header
for1.loopexit: ; preds = %for1.inc19
br label %exit
exit: ; preds = %for1.loopexit
ret void
}