| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: llc -mtriple=amdgpu9.50 < %s | FileCheck %s |
| |
| ; Block placement rotates these loops so that %body, not the LoopInfo header, |
| ; is the backedge destination that gets aligned. The GFX950 fetch-window |
| ; alignment decision must be based on the first instruction of %body. |
| |
| ; %body starts with an 8-byte v_mul_f64 while %header starts with a 4-byte |
| ; s_cmp, so %body must be aligned. |
| define amdgpu_kernel void @rotated_loop_8byte_top_block(ptr addrspace(1) %out, i32 %n, double %x) { |
| ; CHECK-LABEL: rotated_loop_8byte_top_block: |
| ; CHECK: ; %bb.0: ; %entry |
| ; CHECK-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x34 |
| ; CHECK-NEXT: s_load_dword s2, s[4:5], 0x2c |
| ; CHECK-NEXT: s_mov_b32 s3, 0 |
| ; CHECK-NEXT: s_waitcnt lgkmcnt(0) |
| ; CHECK-NEXT: v_mov_b64_e32 v[0:1], s[0:1] |
| ; CHECK-NEXT: s_branch .LBB0_2 |
| ; CHECK-NEXT: .p2align 5, , 4 |
| ; CHECK-NEXT: .LBB0_1: ; %body |
| ; CHECK-NEXT: ; in Loop: Header=BB0_2 Depth=1 |
| ; CHECK-NEXT: v_mul_f64 v[0:1], v[2:3], v[2:3] |
| ; CHECK-NEXT: s_add_i32 s3, s3, 1 |
| ; CHECK-NEXT: s_mov_b64 s[0:1], 0 |
| ; CHECK-NEXT: s_and_b64 s[0:1], s[0:1], exec |
| ; CHECK-NEXT: s_cbranch_scc1 .LBB0_4 |
| ; CHECK-NEXT: .LBB0_2: ; %header |
| ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: s_cmp_ge_i32 s3, s2 |
| ; CHECK-NEXT: v_mov_b64_e32 v[2:3], v[0:1] |
| ; CHECK-NEXT: s_cbranch_scc0 .LBB0_1 |
| ; CHECK-NEXT: ; %bb.3: ; in Loop: Header=BB0_2 Depth=1 |
| ; CHECK-NEXT: s_mov_b64 s[0:1], -1 |
| ; CHECK-NEXT: ; implicit-def: $vgpr0_vgpr1 |
| ; CHECK-NEXT: ; implicit-def: $sgpr3 |
| ; CHECK-NEXT: s_and_b64 s[0:1], s[0:1], exec |
| ; CHECK-NEXT: s_cbranch_scc0 .LBB0_2 |
| ; CHECK-NEXT: .LBB0_4: ; %exit |
| ; CHECK-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24 |
| ; CHECK-NEXT: v_mov_b32_e32 v0, 0 |
| ; CHECK-NEXT: s_waitcnt lgkmcnt(0) |
| ; CHECK-NEXT: global_store_dwordx2 v0, v[2:3], s[0:1] |
| ; CHECK-NEXT: s_endpgm |
| entry: |
| br label %header |
| |
| header: |
| %i = phi i32 [ 0, %entry ], [ %i.next, %body ] |
| %acc = phi double [ %x, %entry ], [ %acc.next, %body ] |
| %cmp = icmp slt i32 %i, %n |
| br i1 %cmp, label %body, label %exit |
| |
| body: |
| %acc.next = fmul double %acc, %acc |
| %i.next = add i32 %i, 1 |
| br label %header |
| |
| exit: |
| store double %acc, ptr addrspace(1) %out |
| ret void |
| } |
| |
| ; %body starts with a 4-byte s_add while %header starts with an 8-byte s_cmp |
| ; with a literal operand, so %body must not be aligned. |
| define amdgpu_kernel void @rotated_loop_4byte_top_block(ptr addrspace(1) %out, i32 %n, double %x) { |
| ; CHECK-LABEL: rotated_loop_4byte_top_block: |
| ; CHECK: ; %bb.0: ; %entry |
| ; CHECK-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x34 |
| ; CHECK-NEXT: s_load_dword s2, s[4:5], 0x2c |
| ; CHECK-NEXT: s_mov_b32 s3, 0 |
| ; CHECK-NEXT: s_waitcnt lgkmcnt(0) |
| ; CHECK-NEXT: v_mov_b64_e32 v[0:1], s[0:1] |
| ; CHECK-NEXT: s_branch .LBB1_2 |
| ; CHECK-NEXT: .LBB1_1: ; %body |
| ; CHECK-NEXT: ; in Loop: Header=BB1_2 Depth=1 |
| ; CHECK-NEXT: s_add_i32 s3, s3, s2 |
| ; CHECK-NEXT: v_add_f64 v[0:1], v[2:3], 1.0 |
| ; CHECK-NEXT: s_mov_b64 s[0:1], 0 |
| ; CHECK-NEXT: s_and_b64 s[0:1], s[0:1], exec |
| ; CHECK-NEXT: s_cbranch_scc1 .LBB1_4 |
| ; CHECK-NEXT: .LBB1_2: ; %header |
| ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: s_cmp_gt_i32 s3, 0xf423f |
| ; CHECK-NEXT: v_mul_f64 v[2:3], v[0:1], v[0:1] |
| ; CHECK-NEXT: s_cbranch_scc0 .LBB1_1 |
| ; CHECK-NEXT: ; %bb.3: ; in Loop: Header=BB1_2 Depth=1 |
| ; CHECK-NEXT: s_mov_b64 s[0:1], -1 |
| ; CHECK-NEXT: ; implicit-def: $vgpr0_vgpr1 |
| ; CHECK-NEXT: ; implicit-def: $sgpr3 |
| ; CHECK-NEXT: s_and_b64 s[0:1], s[0:1], exec |
| ; CHECK-NEXT: s_cbranch_scc0 .LBB1_2 |
| ; CHECK-NEXT: .LBB1_4: ; %exit |
| ; CHECK-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24 |
| ; CHECK-NEXT: v_mov_b32_e32 v0, 0 |
| ; CHECK-NEXT: s_waitcnt lgkmcnt(0) |
| ; CHECK-NEXT: global_store_dwordx2 v0, v[2:3], s[0:1] |
| ; CHECK-NEXT: s_endpgm |
| entry: |
| br label %header |
| |
| header: |
| %i = phi i32 [ 0, %entry ], [ %i.next, %body ] |
| %acc = phi double [ %x, %entry ], [ %acc.next, %body ] |
| %acc.sq = fmul double %acc, %acc |
| %cmp = icmp slt i32 %i, 1000000 |
| br i1 %cmp, label %body, label %exit |
| |
| body: |
| %i.next = add i32 %i, %n |
| %acc.next = fadd double %acc.sq, 1.0 |
| br label %header |
| |
| exit: |
| store double %acc.sq, ptr addrspace(1) %out |
| ret void |
| } |