| ; REQUIRES: asserts | |
| ; RUN: opt < %s -passes=loop-interchange -loop-interchange-profitabilities=ignore -debug-only=loop-interchange -disable-output -S 2>%t | |
| ; RUN: FileCheck --input-file=%t %s | |
| ; This test documents a currently missed optimization opportunity. | |
| ; | |
| ; collectPerfectNests() walks up from each innermost loop and stops as soon as | |
| ; it reaches a loop with more than one subloop. But because [loop.i, loop.j] is never put in | |
| ; any LoopList, the pass never analyses or attempts that interchange — the | |
| ; opportunity is silently missed. | |
| ; | |
| ; Corresponding C code: | |
| ; | |
| ; for (int i = 0; i < 8; ++i) | |
| ; for (int j = 0; j < 8; ++j) { | |
| ; A[i][j] = 0; // missed: i/j interchange | |
| ; for (int k = 0; k < 8; ++k) { | |
| ; for (int l = 0; l < 8; ++l) | |
| ; for (int m = 0; m < 8; ++m) | |
| ; Left[m][l] = 0; // interchanged: l/m swapped | |
| ; for (int n = 0; n < 8; ++n) | |
| ; for (int o = 0; o < 8; ++o) | |
| ; Right[o][n] = 0; // interchanged: n/o swapped | |
| ; } | |
| ; } | |
| ; | |
| ; | |
| ; CHECK: Processing LoopList of size = 2 containing the following loops: | |
| ; CHECK-NEXT: - Loop at depth 4 containing: %loop.l.header<header>,%loop.m.header,%loop.m.latch,%loop.l.latch<latch><exiting> | |
| ; CHECK-NEXT: Loop at depth 5 containing: %loop.m.header<header>,%loop.m.latch<latch><exiting> | |
| ; CHECK-NEXT: - Loop at depth 5 containing: %loop.m.header<header>,%loop.m.latch<latch><exiting> | |
| ; CHECK: Loops interchanged: outer loop 'loop.l.header' and inner loop 'loop.m.header' | |
| ; | |
| ; CHECK: Processing LoopList of size = 2 containing the following loops: | |
| ; CHECK-NEXT: - Loop at depth 4 containing: %loop.n.header<header>,%loop.o.header,%loop.o.latch,%loop.n.latch<latch><exiting> | |
| ; CHECK-NEXT: Loop at depth 5 containing: %loop.o.header<header>,%loop.o.latch<latch><exiting> | |
| ; CHECK-NEXT: - Loop at depth 5 containing: %loop.o.header<header>,%loop.o.latch<latch><exiting> | |
| ; CHECK: Loops interchanged: outer loop 'loop.n.header' and inner loop 'loop.o.header' | |
| ; | |
| ; | |
| ; CHECK-NOT: loop.i.header | |
| ; CHECK-NOT: loop.j.header | |
| define void @missed_outer_prefix_subnest(ptr noalias %Left, ptr noalias %Right, | |
| ptr noalias %A) { | |
| entry: | |
| br label %loop.i.header | |
| loop.i.header: | |
| %i = phi i64 [ 0, %entry ], [ %i.next, %loop.i.latch ] | |
| br label %loop.j.header | |
| loop.j.header: | |
| %j = phi i64 [ 0, %loop.i.header ], [ %j.next, %loop.j.latch ] | |
| %a.row = mul nuw nsw i64 %i, 8 | |
| %a.idx = add nuw nsw i64 %a.row, %j | |
| %a.ptr = getelementptr i8, ptr %A, i64 %a.idx | |
| store i8 0, ptr %a.ptr, align 1 | |
| br label %loop.k.header | |
| loop.k.header: | |
| %k = phi i64 [ 0, %loop.j.header ], [ %k.next, %loop.k.latch ] | |
| br label %loop.l.header | |
| loop.l.header: | |
| %l = phi i64 [ 0, %loop.k.header ], [ %l.next, %loop.l.latch ] | |
| br label %loop.m.header | |
| loop.m.header: | |
| %m = phi i64 [ 0, %loop.l.header ], [ %m.next, %loop.m.latch ] | |
| %left.row.base = mul nuw nsw i64 %m, 8 | |
| %left.index = add nuw nsw i64 %left.row.base, %l | |
| %left.element.ptr = getelementptr i8, ptr %Left, i64 %left.index | |
| store i8 0, ptr %left.element.ptr, align 1 | |
| br label %loop.m.latch | |
| loop.m.latch: | |
| %m.next = add nuw nsw i64 %m, 1 | |
| %m.done = icmp eq i64 %m.next, 8 | |
| br i1 %m.done, label %loop.l.latch, label %loop.m.header | |
| loop.l.latch: | |
| %l.next = add nuw nsw i64 %l, 1 | |
| %l.done = icmp eq i64 %l.next, 8 | |
| br i1 %l.done, label %loop.n.header, label %loop.l.header | |
| loop.n.header: | |
| %n = phi i64 [ 0, %loop.l.latch ], [ %n.next, %loop.n.latch ] | |
| br label %loop.o.header | |
| loop.o.header: | |
| %o = phi i64 [ 0, %loop.n.header ], [ %o.next, %loop.o.latch ] | |
| %right.row.base = mul nuw nsw i64 %o, 8 | |
| %right.index = add nuw nsw i64 %right.row.base, %n | |
| %right.element.ptr = getelementptr i8, ptr %Right, i64 %right.index | |
| store i8 0, ptr %right.element.ptr, align 1 | |
| br label %loop.o.latch | |
| loop.o.latch: | |
| %o.next = add nuw nsw i64 %o, 1 | |
| %o.done = icmp eq i64 %o.next, 8 | |
| br i1 %o.done, label %loop.n.latch, label %loop.o.header | |
| loop.n.latch: | |
| %n.next = add nuw nsw i64 %n, 1 | |
| %n.done = icmp eq i64 %n.next, 8 | |
| br i1 %n.done, label %loop.k.latch, label %loop.n.header | |
| loop.k.latch: | |
| %k.next = add nuw nsw i64 %k, 1 | |
| %k.done = icmp eq i64 %k.next, 8 | |
| br i1 %k.done, label %loop.j.latch, label %loop.k.header | |
| loop.j.latch: | |
| %j.next = add nuw nsw i64 %j, 1 | |
| %j.done = icmp eq i64 %j.next, 8 | |
| br i1 %j.done, label %loop.i.latch, label %loop.j.header | |
| loop.i.latch: | |
| %i.next = add nuw nsw i64 %i, 1 | |
| %i.done = icmp eq i64 %i.next, 8 | |
| br i1 %i.done, label %exit, label %loop.i.header | |
| exit: | |
| ret void | |
| } |