mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 19:45:40 -04:00

Summary: for.outer: br for.inner for.inner: LI <loop invariant load instruction> for.inner.latch: br for.inner, for.outer.latch for.outer.latch: br for.outer, for.outer.exit LI is a loop invariant load instruction that post dominate for.outer, so LI should be able to move out of the loop nest. However, there is a bug in allLoopPathsLeadToBlock(). Current algorithm of allLoopPathsLeadToBlock() 1. get all the transitive predecessors of the basic block LI belongs to (for.inner) ==> for.outer, for.inner.latch 2. if any successors of any of the predecessors are not for.inner or for.inner's predecessors, then return false 3. return true Although for.inner.latch is for.inner's predecessor, but for.inner dominates for.inner.latch, which means if for.inner.latch is ever executed, for.inner should be as well. It should not return false for cases like this. Author: Whitney (committed by xingxue) Reviewers: kbarton, jdoerfert, Meinersbur, hfinkel, fhahn Reviewed By: jdoerfert Subscribers: hiraditya, jsji, llvm-commits, etiotto, bmahjour Tags: #LLVM Differential Revision: https://reviews.llvm.org/D62418 llvm-svn: 361762
154 lines
4.8 KiB
LLVM
154 lines
4.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -disable-output -print-mustexecute %s 2>&1 | FileCheck %s
|
|
|
|
define i1 @header_with_icf(i32* noalias %p, i32 %high) {
|
|
; CHECK-LABEL: @header_with_icf(
|
|
; CHECK-LABEL: loop:
|
|
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; (mustexec in: loop)
|
|
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
|
|
; CHECK: call void @maythrow_and_use(i32 %v) ; (mustexec in: loop)
|
|
; CHECK-NOT: mustexec
|
|
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [0, %entry], [%iv.next, %loop]
|
|
%v = load i32, i32* %p
|
|
call void @maythrow_and_use(i32 %v)
|
|
%iv.next = add nsw nuw i32 %iv, 1
|
|
%exit.test = icmp slt i32 %iv, %high
|
|
br i1 %exit.test, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @split_header(i32* noalias %p, i32 %high) {
|
|
; CHECK-LABEL: @split_header(
|
|
; CHECK-LABEL: loop:
|
|
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
|
|
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
|
|
; CHECK: br label %next ; (mustexec in: loop)
|
|
; CHECK-NOT: mustexec
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [0, %entry], [%iv.next, %next]
|
|
%v = load i32, i32* %p
|
|
br label %next
|
|
next:
|
|
call void @maythrow_and_use(i32 %v)
|
|
%iv.next = add nsw nuw i32 %iv, 1
|
|
%exit.test = icmp slt i32 %iv, %high
|
|
br i1 %exit.test, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i1 false
|
|
}
|
|
|
|
; FIXME: everything in inner loop header should be must execute
|
|
; for outer as well
|
|
define i1 @nested(i32* noalias %p, i32 %high) {
|
|
; CHECK-LABEL: @nested
|
|
; CHECK-LABEL: loop: ; preds = %next
|
|
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
|
|
; CHECK: br label %inner_loop ; (mustexec in: loop)
|
|
; CHECK-LABEL: inner_loop:
|
|
; CHECK: %v = load i32, i32* %p ; (mustexec in: inner_loop)
|
|
; CHECK: %inner.test = icmp eq i32 %v, 0 ; (mustexec in: inner_loop)
|
|
; CHECK: br i1 %inner.test, label %inner_loop, label %next ; (mustexec in: inner_loop)
|
|
; CHECK-NOT: mustexec
|
|
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [0, %entry], [%iv.next, %next]
|
|
br label %inner_loop
|
|
|
|
inner_loop:
|
|
%v = load i32, i32* %p
|
|
%inner.test = icmp eq i32 %v, 0
|
|
br i1 %inner.test, label %inner_loop, label %next
|
|
|
|
next:
|
|
call void @maythrow_and_use(i32 %v)
|
|
%iv.next = add nsw nuw i32 %iv, 1
|
|
%exit.test = icmp slt i32 %iv, %high
|
|
br i1 %exit.test, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @nested_no_throw(i32* noalias %p, i32 %high) {
|
|
; CHECK-LABEL: @nested_no_throw
|
|
; CHECK-LABEL: loop: ; preds = %next
|
|
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
|
|
; CHECK: br label %inner_loop ; (mustexec in: loop)
|
|
; CHECK-LABEL: inner_loop:
|
|
; CHECK: %v = load i32, i32* %p ; (mustexec in 2 loops: inner_loop, loop)
|
|
; CHECK: %inner.test = icmp eq i32 %v, 0 ; (mustexec in 2 loops: inner_loop, loop)
|
|
; CHECK: br i1 %inner.test, label %inner_loop, label %next ; (mustexec in 2 loops: inner_loop, loop)
|
|
; CHECK-LABEL: next:
|
|
; CHECK: %iv.next = add nuw nsw i32 %iv, 1 ; (mustexec in: loop)
|
|
; CHECK: %exit.test = icmp slt i32 %iv, %high ; (mustexec in: loop)
|
|
; CHECK: br i1 %exit.test, label %exit, label %loop ; (mustexec in: loop)
|
|
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [0, %entry], [%iv.next, %next]
|
|
br label %inner_loop
|
|
|
|
inner_loop:
|
|
%v = load i32, i32* %p
|
|
%inner.test = icmp eq i32 %v, 0
|
|
br i1 %inner.test, label %inner_loop, label %next
|
|
|
|
next:
|
|
%iv.next = add nsw nuw i32 %iv, 1
|
|
%exit.test = icmp slt i32 %iv, %high
|
|
br i1 %exit.test, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i1 false
|
|
}
|
|
|
|
; Since all the instructions in the loop dominate the only exit
|
|
; and there's no implicit control flow in the loop, all must execute
|
|
; FIXME: handled by loop safety info, test it
|
|
define i1 @nothrow_loop(i32* noalias %p, i32 %high) {
|
|
; CHECK-LABEL: @nothrow_loop(
|
|
; CHECK-LABEL: loop:
|
|
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
|
|
; CHECK: br label %next ; (mustexec in: loop)
|
|
; CHECK-LABEL: next:
|
|
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
|
|
; CHECK: %iv.next = add nuw nsw i32 %iv, 1 ; (mustexec in: loop)
|
|
; CHECK: %exit.test = icmp slt i32 %iv, %high ; (mustexec in: loop)
|
|
; CHECK: br i1 %exit.test, label %exit, label %loop ; (mustexec in: loop)
|
|
; CHECK-NOT: mustexec
|
|
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [0, %entry], [%iv.next, %next]
|
|
br label %next
|
|
next:
|
|
%v = load i32, i32* %p
|
|
%iv.next = add nsw nuw i32 %iv, 1
|
|
%exit.test = icmp slt i32 %iv, %high
|
|
br i1 %exit.test, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i1 false
|
|
}
|
|
|
|
|
|
declare void @maythrow_and_use(i32)
|