| ; Test the the loop nest depth is correctly calculated for basic blocks. | |
| ; REQUIRES: allow_dump | |
| ; Single threaded so that the dumps used for checking happen in order. | |
| ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 --verbose=loop \ | |
| ; RUN: -log=%t --threads=0 && FileCheck %s < %t | |
| define internal void @test_single_loop(i32 %a32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| br label %loop0 | |
| loop0: ; <-+ | |
| br label %loop1 ; | | |
| loop1: ; | | |
| br i1 %a, label %loop0, label %out ; --+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_single_loop_with_continue(i32 %a32, i32 %b32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| br label %loop0 | |
| loop0: ; <-+ | |
| br label %loop1 ; | | |
| loop1: ; | | |
| br i1 %a, label %loop0, label %loop2 ; --+ | |
| loop2: ; | | |
| br i1 %b, label %loop0, label %out ; --+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop2: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_multiple_exits(i32 %a32, i32 %b32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| br label %loop0 | |
| loop0: ; <-+ | |
| br label %loop1 ; | | |
| loop1: ; | | |
| br i1 %a, label %loop2, label %out ; --+-+ | |
| loop2: ; | | | |
| br i1 %b, label %loop0, label %out ; --+ | | |
| ; | | |
| out: ; <---+ | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop2: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_two_nested_loops(i32 %a32, i32 %b32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| br label %loop0_0 | |
| loop0_0: ; <---+ | |
| br label %loop1_0 ; | | |
| loop1_0: ; <-+ | | |
| br label %loop1_1 ; | | | |
| loop1_1: ; | | | |
| br i1 %a, label %loop1_0, label %loop0_1 ; --+ | | |
| loop0_1: ; | | |
| br i1 %b, label %loop0_0, label %out ; ----+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0_0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1_0: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop1_1: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop0_1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_two_nested_loops_with_continue(i32 %a32, i32 %b32, | |
| i32 %c32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| %c = trunc i32 %c32 to i1 | |
| br label %loop0_0 | |
| loop0_0: ; <---+ | |
| br label %loop1_0 ; | | |
| loop1_0: ; <-+ | | |
| br label %loop1_1 ; | | | |
| loop1_1: ; | | | |
| br i1 %a, label %loop1_0, label %loop1_2 ; --+ | | |
| loop1_2: ; | | | |
| br i1 %a, label %loop1_0, label %loop0_1 ; --+ | | |
| loop0_1: ; | | |
| br i1 %b, label %loop0_0, label %out ; ----+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0_0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1_0: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop1_1: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop1_2: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop0_1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_multiple_nested_loops(i32 %a32, i32 %b32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| br label %loop0_0 | |
| loop0_0: ; <---+ | |
| br label %loop1_0 ; | | |
| loop1_0: ; <-+ | | |
| br label %loop1_1 ; | | | |
| loop1_1: ; | | | |
| br i1 %a, label %loop1_0, label %loop0_1 ; --+ | | |
| loop0_1: ; | | |
| br label %loop2_0 ; | | |
| loop2_0: ; <-+ | | |
| br label %loop2_1 ; | | | |
| loop2_1: ; | | | |
| br i1 %a, label %loop2_0, label %loop0_2 ; --+ | | |
| loop0_2: ; | | |
| br i1 %b, label %loop0_0, label %out ; ----+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0_0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1_0: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop1_1: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop0_1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop2_0: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop2_1: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop0_2: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_three_nested_loops(i32 %a32, i32 %b32, i32 %c32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| %b = trunc i32 %b32 to i1 | |
| %c = trunc i32 %c32 to i1 | |
| br label %loop0_0 | |
| loop0_0: ; <-----+ | |
| br label %loop1_0 ; | | |
| loop1_0: ; <---+ | | |
| br label %loop2_0 ; | | | |
| loop2_0: ; <-+ | | | |
| br label %loop2_1 ; | | | | |
| loop2_1: ; | | | | |
| br i1 %a, label %loop2_0, label %loop1_1 ; --+ | | | |
| loop1_1: ; | | | |
| br i1 %b, label %loop1_0, label %loop0_1 ; ----+ | | |
| loop0_1: ; | | |
| br i1 %c, label %loop0_0, label %out ; ------+ | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: loop0_0: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: loop1_0: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop2_0: | |
| ; CHECK-NEXT: LoopNestDepth = 3 | |
| ; CHECK-NEXT: loop2_1: | |
| ; CHECK-NEXT: LoopNestDepth = 3 | |
| ; CHECK-NEXT: loop1_1: | |
| ; CHECK-NEXT: LoopNestDepth = 2 | |
| ; CHECK-NEXT: loop0_1: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_diamond(i32 %a32) { | |
| entry: | |
| %a = trunc i32 %a32 to i1 | |
| br i1 %a, label %left, label %right | |
| left: | |
| br label %out | |
| right: | |
| br label %out | |
| out: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: left: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: right: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: out: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW | |
| define internal void @test_single_block_loop(i32 %count) { | |
| entry: | |
| br label %body | |
| body: | |
| ; %i = phi i32 [ 0, %entry ], [ %inc, %body ] | |
| ; A normal loop would have a phi instruction like above for the induction | |
| ; variable, but that may introduce new basic blocks due to phi edge splitting, | |
| ; so we use an alternative definition for %i to make the test more clear. | |
| %i = add i32 %count, 1 | |
| %inc = add i32 %i, 1 | |
| %cmp = icmp slt i32 %inc, %count | |
| br i1 %cmp, label %body, label %exit | |
| exit: | |
| ret void | |
| } | |
| ; CHECK-LABEL: After loop analysis | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-NEXT: body: | |
| ; CHECK-NEXT: LoopNestDepth = 1 | |
| ; CHECK-NEXT: exit: | |
| ; CHECK-NEXT: LoopNestDepth = 0 | |
| ; CHECK-LABEL: Before RMW |