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
|
|
}
|