mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
cc445a07d6
Currently we only rely on the induction increment to come before the condition to ensure the required instructions get moved to the new latch. This patch duplicates and moves the required instructions to the newly created latch. We move the condition to the end of the new block, then process its operands. We stop at operands that are defined outside the loop, or are the induction PHI. We duplicate the instructions and update the uses in the moved instructions, to ensure other users remain intact. See the added test2 for such an example. Reviewers: efriedma, mcrosier Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D67367 llvm-svn: 371595
201 lines
7.9 KiB
LLVM
201 lines
7.9 KiB
LLVM
; RUN: opt < %s -loop-interchange -loop-interchange-threshold=-100 -verify-loop-lcssa -S | FileCheck %s
|
|
|
|
; Test case for PR41725. The induction variables in the latches escape the
|
|
; loops and we must move some PHIs around.
|
|
|
|
@a = common dso_local global i64 0, align 4
|
|
@b = common dso_local global i64 0, align 4
|
|
@c = common dso_local global [10 x [1 x i32 ]] zeroinitializer, align 16
|
|
|
|
|
|
define void @test_lcssa_indvars1() {
|
|
; CHECK-LABEL: @test_lcssa_indvars1()
|
|
; CHECK-LABEL: inner.body:
|
|
; CHECK-NEXT: %iv.inner = phi i64 [ %[[IVNEXT:[0-9]+]], %inner.body.split ], [ 5, %inner.body.preheader ]
|
|
|
|
; CHECK-LABEL: inner.body.split:
|
|
; CHECK-NEXT: %0 = phi i64 [ %iv.outer.next, %outer.latch ]
|
|
; CHECK-NEXT: %[[IVNEXT]] = add nsw i64 %iv.inner, -1
|
|
; CHECK-NEXT: %[[COND:[0-9]+]] = icmp eq i64 %iv.inner, 0
|
|
; CHECK-NEXT: br i1 %[[COND]], label %exit, label %inner.body
|
|
|
|
; CHECK-LABEL: exit:
|
|
; CHECK-NEXT: %v4.lcssa = phi i64 [ %0, %inner.body.split ]
|
|
; CHECK-NEXT: %v8.lcssa.lcssa = phi i64 [ %[[IVNEXT]], %inner.body.split ]
|
|
; CHECK-NEXT: store i64 %v8.lcssa.lcssa, i64* @b, align 4
|
|
; CHECK-NEXT: store i64 %v4.lcssa, i64* @a, align 4
|
|
|
|
entry:
|
|
br label %outer.header
|
|
|
|
outer.header: ; preds = %outer.latch, %entry
|
|
%iv.outer = phi i64 [ 0, %entry ], [ %iv.outer.next, %outer.latch ]
|
|
br label %inner.body
|
|
|
|
inner.body: ; preds = %inner.body, %outer.header
|
|
%iv.inner = phi i64 [ 5, %outer.header ], [ %iv.inner.next, %inner.body ]
|
|
%v7 = getelementptr inbounds [10 x [1 x i32]], [10 x [1 x i32]]* @c, i64 0, i64 %iv.inner, i64 %iv.outer
|
|
store i32 0, i32* %v7, align 4
|
|
%iv.inner.next = add nsw i64 %iv.inner, -1
|
|
%v9 = icmp eq i64 %iv.inner, 0
|
|
br i1 %v9, label %outer.latch, label %inner.body
|
|
|
|
outer.latch: ; preds = %inner.body
|
|
%v8.lcssa = phi i64 [ %iv.inner.next, %inner.body ]
|
|
%iv.outer.next = add nuw nsw i64 %iv.outer, 1
|
|
%v5 = icmp ult i64 %iv.outer, 2
|
|
br i1 %v5, label %outer.header, label %exit
|
|
|
|
exit: ; preds = %outer.latch
|
|
%v4.lcssa = phi i64 [ %iv.outer.next, %outer.latch ]
|
|
%v8.lcssa.lcssa = phi i64 [ %v8.lcssa, %outer.latch ]
|
|
store i64 %v8.lcssa.lcssa, i64* @b, align 4
|
|
store i64 %v4.lcssa, i64* @a, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @test_lcssa_indvars2() {
|
|
; CHECK-LABEL: @test_lcssa_indvars2()
|
|
; CHECK-LABEL: inner.body:
|
|
; CHECK-NEXT: %iv.inner = phi i64 [ %[[IVNEXT:[0-9]+]], %inner.body.split ], [ 5, %inner.body.preheader ]
|
|
|
|
; CHECK-LABEL: inner.body.split:
|
|
; CHECK-NEXT: %0 = phi i64 [ %iv.outer, %outer.latch ]
|
|
; CHECK-NEXT: %[[IVNEXT]] = add nsw i64 %iv.inner, -1
|
|
; CHECK-NEXT: %[[COND:[0-9]+]] = icmp eq i64 %[[IVNEXT]], 0
|
|
; CHECK-NEXT: br i1 %[[COND]], label %exit, label %inner.body
|
|
|
|
; CHECK-LABEL: exit:
|
|
; CHECK-NEXT: %v4.lcssa = phi i64 [ %0, %inner.body.split ]
|
|
; CHECK-NEXT: %v8.lcssa.lcssa = phi i64 [ %iv.inner, %inner.body.split ]
|
|
; CHECK-NEXT: store i64 %v8.lcssa.lcssa, i64* @b, align 4
|
|
; CHECK-NEXT: store i64 %v4.lcssa, i64* @a, align 4
|
|
|
|
entry:
|
|
br label %outer.header
|
|
|
|
outer.header: ; preds = %outer.latch, %entry
|
|
%iv.outer = phi i64 [ 0, %entry ], [ %iv.outer.next, %outer.latch ]
|
|
br label %inner.body
|
|
|
|
inner.body: ; preds = %inner.body, %outer.header
|
|
%iv.inner = phi i64 [ 5, %outer.header ], [ %iv.inner.next, %inner.body ]
|
|
%v7 = getelementptr inbounds [10 x [1 x i32]], [10 x [1 x i32]]* @c, i64 0, i64 %iv.inner, i64 %iv.outer
|
|
store i32 0, i32* %v7, align 4
|
|
%iv.inner.next = add nsw i64 %iv.inner, -1
|
|
%v9 = icmp eq i64 %iv.inner.next, 0
|
|
br i1 %v9, label %outer.latch, label %inner.body
|
|
|
|
outer.latch: ; preds = %inner.body
|
|
%v8.lcssa = phi i64 [ %iv.inner, %inner.body ]
|
|
%iv.outer.next = add nuw nsw i64 %iv.outer, 1
|
|
%v5 = icmp ult i64 %iv.outer.next, 2
|
|
br i1 %v5, label %outer.header, label %exit
|
|
|
|
exit: ; preds = %outer.latch
|
|
%v4.lcssa = phi i64 [ %iv.outer, %outer.latch ]
|
|
%v8.lcssa.lcssa = phi i64 [ %v8.lcssa, %outer.latch ]
|
|
store i64 %v8.lcssa.lcssa, i64* @b, align 4
|
|
store i64 %v4.lcssa, i64* @a, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @test_lcssa_indvars3() {
|
|
; CHECK-LABEL: @test_lcssa_indvars3()
|
|
; CHECK-LABEL: inner.body:
|
|
; CHECK-NEXT: %iv.inner = phi i64 [ %[[IVNEXT:[0-9]+]], %inner.body.split ], [ 5, %inner.body.preheader ]
|
|
|
|
; CHECK-LABEL: inner.body.split:
|
|
; CHECK-NEXT: %0 = phi i64 [ %iv.outer.next, %outer.latch ]
|
|
; CHECK-NEXT: %[[IVNEXT]] = add nsw i64 %iv.inner, -1
|
|
; CHECK-NEXT: %[[COND:[0-9]+]] = icmp eq i64 %iv.inner, 0
|
|
; CHECK-NEXT: br i1 %[[COND]], label %exit, label %inner.body
|
|
|
|
; CHECK-LABEL: exit:
|
|
; CHECK-NEXT: %v4.lcssa = phi i64 [ %0, %inner.body.split ]
|
|
; CHECK-NEXT: %v8.lcssa.lcssa = phi i64 [ %[[IVNEXT]], %inner.body.split ]
|
|
; CHECK-NEXT: %v8.lcssa.lcssa.2 = phi i64 [ %[[IVNEXT]], %inner.body.split ]
|
|
; CHECK-NEXT: %r1 = add i64 %v8.lcssa.lcssa, %v8.lcssa.lcssa.2
|
|
; CHECK-NEXT: store i64 %r1, i64* @b, align 4
|
|
; CHECK-NEXT: store i64 %v4.lcssa, i64* @a, align 4
|
|
|
|
|
|
entry:
|
|
br label %outer.header
|
|
|
|
outer.header: ; preds = %outer.latch, %entry
|
|
%iv.outer = phi i64 [ 0, %entry ], [ %iv.outer.next, %outer.latch ]
|
|
br label %inner.body
|
|
|
|
inner.body: ; preds = %inner.body, %outer.header
|
|
%iv.inner = phi i64 [ 5, %outer.header ], [ %iv.inner.next, %inner.body ]
|
|
%v7 = getelementptr inbounds [10 x [1 x i32]], [10 x [1 x i32]]* @c, i64 0, i64 %iv.inner, i64 %iv.outer
|
|
store i32 0, i32* %v7, align 4
|
|
%iv.inner.next = add nsw i64 %iv.inner, -1
|
|
%v9 = icmp eq i64 %iv.inner, 0
|
|
br i1 %v9, label %outer.latch, label %inner.body
|
|
|
|
outer.latch: ; preds = %inner.body
|
|
%v8.lcssa = phi i64 [ %iv.inner.next, %inner.body ]
|
|
;%const.lcssa = phi i64 [ 111, %inner.body ]
|
|
%iv.outer.next = add nuw nsw i64 %iv.outer, 1
|
|
%v5 = icmp ult i64 %iv.outer, 2
|
|
br i1 %v5, label %outer.header, label %exit
|
|
|
|
exit: ; preds = %outer.latch
|
|
%v4.lcssa = phi i64 [ %iv.outer.next, %outer.latch ]
|
|
%v8.lcssa.lcssa = phi i64 [ %v8.lcssa, %outer.latch ]
|
|
%v8.lcssa.lcssa.2 = phi i64 [ %v8.lcssa, %outer.latch ]
|
|
%r1 = add i64 %v8.lcssa.lcssa, %v8.lcssa.lcssa.2
|
|
store i64 %r1, i64* @b, align 4
|
|
store i64 %v4.lcssa, i64* @a, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; Make sure we do not crash for loops without reachable exits.
|
|
define void @no_reachable_exits() {
|
|
; Check we interchanged.
|
|
; CHECK-LABEL: @no_reachable_exits() {
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: br label %inner.ph
|
|
; CHECK-LABEL: outer.ph:
|
|
; CHECK-NEXT: br label %outer.header
|
|
; CHECK-LABEL: inner.ph:
|
|
; CHECK-NEXT: br label %inner.body
|
|
; CHECK-LABEL: inner.body:
|
|
; CHECK-NEXT: %tmp31 = phi i32 [ 0, %inner.ph ], [ %[[IVNEXT:[0-9]]], %inner.body.split ]
|
|
; CHECK-NEXT: br label %outer.ph
|
|
; CHECK-LABEL: inner.body.split:
|
|
; CHECK-NEXT: %[[IVNEXT]] = add nsw i32 %tmp31, 1
|
|
; CHECK-NEXT: br i1 false, label %inner.body, label %exit
|
|
|
|
|
|
bb:
|
|
br label %outer.ph
|
|
|
|
outer.ph: ; preds = %bb
|
|
br label %outer.header
|
|
|
|
outer.header: ; preds = %outer.ph, %outer.latch
|
|
%tmp2 = phi i32 [ 0, %outer.ph ], [ %tmp8, %outer.latch ]
|
|
br i1 undef, label %inner.ph, label %outer.latch
|
|
|
|
inner.ph: ; preds = %outer.header
|
|
br label %inner.body
|
|
|
|
inner.body: ; preds = %inner.ph, %inner.body
|
|
%tmp31 = phi i32 [ 0, %inner.ph ], [ %tmp6, %inner.body]
|
|
%tmp5 = load i32*, i32** undef, align 8
|
|
%tmp6 = add nsw i32 %tmp31, 1
|
|
br i1 undef, label %inner.body, label %outer.latch
|
|
|
|
outer.latch: ; preds = %inner.body, %outer.header
|
|
%tmp8 = add nsw i32 %tmp2, 1
|
|
br i1 undef, label %outer.header, label %exit
|
|
|
|
exit: ; preds = %outer.latch
|
|
unreachable
|
|
}
|