llvm-project/llvm/test/Transforms/LoopInterchange/interchanged-loop-nest-4.ll
Congzhe Cao 6782d71680 [LoopPassManager] Ensure to construct loop nests with the outermost loop
This patch is to resolve the bug reported and discussed in
https://reviews.llvm.org/D124926#3718761 and https://reviews.llvm.org/D124926#3719876.

The problem is that loop interchange is a loopnest pass under the new pass manager,
but the loop nest may not be constructed correctly by the loop pass manager after
running loop interchange and before running the next pass, which might cause problems
when it continues running the next pass.

The reason that the loop nest is constructed incorrectly is that the outermost
loop might have changed after interchange, and what was the original outermost
loop is not the current outermost loop anymore. Constructing the loop nest based
on the original outermost loop would generate an invalid loop nest.

The fix in this patch is that, in the loop pass manager before running each loopnest
pass, we re-cosntruct the loop nest based on the current outermost loop, if LPMUpdater
notifies the loop pass manager that the previous loop nest has been invalidated by passes
like loop interchange.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D132199
2022-09-21 23:59:26 -04:00

54 lines
2.5 KiB
LLVM

; REQUIRES: asserts
; RUN: opt < %s -passes="loop(loop-interchange,loop-interchange)" -cache-line-size=8 -verify-dom-info -verify-loop-info \
; RUN: -debug-only=loop-interchange 2>&1 | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@g_75 = external global i32, align 1
@g_78 = external global [6 x ptr], align 1
; Loop interchange as a loopnest pass should always construct the loop nest from
; the outermost loop. This test case runs loop interchange twice. In the loop pass
; manager, it might occur that after the first loop interchange transformation
; the original outermost loop becomes a inner loop hence the loop nest constructed
; afterwards for the second loop interchange pass turns out to be a loop list of size
; 2 and is not valid. This causes functional issues.
;
; Make sure we always construct the valid and correct loop nest at the beginning
; of execution of a loopnest pass.
; CHECK: Processing LoopList of size = 3
; CHECK: Processing LoopList of size = 3
define void @loopnest_01() {
entry:
br label %for.cond5.preheader.i.i.i
for.cond5.preheader.i.i.i: ; preds = %for.end16.i.i.i, %entry
%storemerge11.i.i.i = phi i32 [ 4, %entry ], [ %sub18.i.i.i, %for.end16.i.i.i ]
br label %for.cond8.preheader.i.i.i
for.cond8.preheader.i.i.i: ; preds = %for.inc14.i.i.i, %for.cond5.preheader.i.i.i
%l_105.18.i.i.i = phi i16 [ 0, %for.cond5.preheader.i.i.i ], [ %add15.i.i.i, %for.inc14.i.i.i ]
br label %for.body10.i.i.i
for.body10.i.i.i: ; preds = %for.body10.i.i.i, %for.cond8.preheader.i.i.i
%storemerge56.i.i.i = phi i16 [ 5, %for.cond8.preheader.i.i.i ], [ %sub.i.i.i, %for.body10.i.i.i ]
%arrayidx.i.i.i = getelementptr [6 x ptr], ptr @g_78, i16 0, i16 %storemerge56.i.i.i
store ptr @g_75, ptr %arrayidx.i.i.i, align 1
%sub.i.i.i = add nsw i16 %storemerge56.i.i.i, -1
br i1 true, label %for.inc14.i.i.i, label %for.body10.i.i.i
for.inc14.i.i.i: ; preds = %for.body10.i.i.i
%add15.i.i.i = add nuw nsw i16 %l_105.18.i.i.i, 1
%exitcond.not.i.i.i = icmp eq i16 %add15.i.i.i, 6
br i1 %exitcond.not.i.i.i, label %for.end16.i.i.i, label %for.cond8.preheader.i.i.i
for.end16.i.i.i: ; preds = %for.inc14.i.i.i
%sub18.i.i.i = add nsw i32 %storemerge11.i.i.i, -1
%cmp.i10.not.i.i = icmp eq i32 %storemerge11.i.i.i, 0
br i1 %cmp.i10.not.i.i, label %func_4.exit.i, label %for.cond5.preheader.i.i.i
func_4.exit.i: ; preds = %for.end16.i.i.i
unreachable
}