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 inc8bd6ea35e. A workaround was introduced later ineac3487510to 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 ofc8bd6ea35e. 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.
99 lines
4.5 KiB
LLVM
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
|
|
}
|