| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_75 -mattr=+ptx82 | FileCheck %s --check-prefix=PTX82 |
| ; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_75 -mattr=+ptx83 | FileCheck %s --check-prefix=PTX83 |
| ; RUN: %if ptxas-sm_75 && ptxas-isa-8.2 %{ llc < %s -mtriple=nvptx64 -mcpu=sm_75 -mattr=+ptx82 | %ptxas-verify -arch=sm_75 %} |
| ; RUN: %if ptxas-sm_75 && ptxas-isa-8.3 %{ llc < %s -mtriple=nvptx64 -mcpu=sm_75 -mattr=+ptx83 | %ptxas-verify -arch=sm_75 %} |
| |
| target triple = "nvptx64-nvidia-cuda" |
| |
| define internal i32 @callee(i32 %x) noinline { |
| ; PTX82-LABEL: callee( |
| ; PTX82: { |
| ; PTX82-NEXT: .reg .b32 %r<3>; |
| ; PTX82-EMPTY: |
| ; PTX82-NEXT: // %bb.0: |
| ; PTX82-NEXT: ld.param.b32 %r1, [callee_param_0]; |
| ; PTX82-NEXT: add.s32 %r2, %r1, 1; |
| ; PTX82-NEXT: st.param.b32 [func_retval0], %r2; |
| ; PTX82-NEXT: ret; |
| ; |
| ; PTX83-LABEL: callee( |
| ; PTX83: { |
| ; PTX83-NEXT: .reg .b32 %r<3>; |
| ; PTX83-EMPTY: |
| ; PTX83-NEXT: // %bb.0: |
| ; PTX83-NEXT: ld.param::func.b32 %r1, [callee_param_0]; |
| ; PTX83-NEXT: add.s32 %r2, %r1, 1; |
| ; PTX83-NEXT: st.param::func.b32 [func_retval0], %r2; |
| ; PTX83-NEXT: ret; |
| %y = add i32 %x, 1 |
| ret i32 %y |
| } |
| |
| define ptx_kernel void @kernel(i32 %x, ptr %out) { |
| ; PTX82-LABEL: kernel( |
| ; PTX82: { |
| ; PTX82-NEXT: .reg .b32 %r<3>; |
| ; PTX82-NEXT: .reg .b64 %rd<3>; |
| ; PTX82-EMPTY: |
| ; PTX82-NEXT: // %bb.0: |
| ; PTX82-NEXT: ld.param.b32 %r1, [kernel_param_0]; |
| ; PTX82-NEXT: ld.param.b64 %rd1, [kernel_param_1]; |
| ; PTX82-NEXT: cvta.to.global.u64 %rd2, %rd1; |
| ; PTX82-NEXT: { // callseq 0, 0 |
| ; PTX82-NEXT: .param .b32 param0; |
| ; PTX82-NEXT: .param .b32 retval0; |
| ; PTX82-NEXT: st.param.b32 [param0], %r1; |
| ; PTX82-NEXT: call.uni (retval0), callee, (param0); |
| ; PTX82-NEXT: ld.param.b32 %r2, [retval0]; |
| ; PTX82-NEXT: } // callseq 0 |
| ; PTX82-NEXT: st.global.b32 [%rd2], %r2; |
| ; PTX82-NEXT: ret; |
| ; |
| ; PTX83-LABEL: kernel( |
| ; PTX83: { |
| ; PTX83-NEXT: .reg .b32 %r<3>; |
| ; PTX83-NEXT: .reg .b64 %rd<3>; |
| ; PTX83-EMPTY: |
| ; PTX83-NEXT: // %bb.0: |
| ; PTX83-NEXT: ld.param::entry.b32 %r1, [kernel_param_0]; |
| ; PTX83-NEXT: ld.param::entry.b64 %rd1, [kernel_param_1]; |
| ; PTX83-NEXT: cvta.to.global.u64 %rd2, %rd1; |
| ; PTX83-NEXT: { // callseq 0, 0 |
| ; PTX83-NEXT: .param .b32 param0; |
| ; PTX83-NEXT: .param .b32 retval0; |
| ; PTX83-NEXT: st.param::func.b32 [param0], %r1; |
| ; PTX83-NEXT: call.uni (retval0), callee, (param0); |
| ; PTX83-NEXT: ld.param::func.b32 %r2, [retval0]; |
| ; PTX83-NEXT: } // callseq 0 |
| ; PTX83-NEXT: st.global.b32 [%rd2], %r2; |
| ; PTX83-NEXT: ret; |
| %ret = call i32 @callee(i32 %x) |
| store i32 %ret, ptr %out |
| ret void |
| } |
| |
| ; A device function that loads through a ptr addrspace(101) (entry param ref |
| ; passed from a kernel). The ::entry subqualifier on the register-indirect |
| ; ld.param is required and older ptxas miscompiles this without it. |
| |
| define internal i32 @callee_entry_param(ptr addrspace(101) %p) noinline { |
| ; PTX82-LABEL: callee_entry_param( |
| ; PTX82: { |
| ; PTX82-NEXT: .reg .b32 %r<2>; |
| ; PTX82-NEXT: .reg .b64 %rd<2>; |
| ; PTX82-EMPTY: |
| ; PTX82-NEXT: // %bb.0: |
| ; PTX82-NEXT: ld.param.b64 %rd1, [callee_entry_param_param_0]; |
| ; PTX82-NEXT: ld.param.b32 %r1, [%rd1]; |
| ; PTX82-NEXT: st.param.b32 [func_retval0], %r1; |
| ; PTX82-NEXT: ret; |
| ; |
| ; PTX83-LABEL: callee_entry_param( |
| ; PTX83: { |
| ; PTX83-NEXT: .reg .b32 %r<2>; |
| ; PTX83-NEXT: .reg .b64 %rd<2>; |
| ; PTX83-EMPTY: |
| ; PTX83-NEXT: // %bb.0: |
| ; PTX83-NEXT: ld.param::func.b64 %rd1, [callee_entry_param_param_0]; |
| ; PTX83-NEXT: ld.param::entry.b32 %r1, [%rd1]; |
| ; PTX83-NEXT: st.param::func.b32 [func_retval0], %r1; |
| ; PTX83-NEXT: ret; |
| %v = load i32, ptr addrspace(101) %p, align 4 |
| ret i32 %v |
| } |
| |
| define ptx_kernel void @kernel_pass_param_ref(ptr byval(i32) align 4 "nvvm.grid_constant" %input, ptr %out) { |
| ; PTX82-LABEL: kernel_pass_param_ref( |
| ; PTX82: { |
| ; PTX82-NEXT: .reg .b32 %r<2>; |
| ; PTX82-NEXT: .reg .b64 %rd<4>; |
| ; PTX82-EMPTY: |
| ; PTX82-NEXT: // %bb.0: |
| ; PTX82-NEXT: mov.b64 %rd1, kernel_pass_param_ref_param_0; |
| ; PTX82-NEXT: ld.param.b64 %rd2, [kernel_pass_param_ref_param_1]; |
| ; PTX82-NEXT: cvta.to.global.u64 %rd3, %rd2; |
| ; PTX82-NEXT: { // callseq 1, 0 |
| ; PTX82-NEXT: .param .b64 param0; |
| ; PTX82-NEXT: .param .b32 retval0; |
| ; PTX82-NEXT: st.param.b64 [param0], %rd1; |
| ; PTX82-NEXT: call.uni (retval0), callee_entry_param, (param0); |
| ; PTX82-NEXT: ld.param.b32 %r1, [retval0]; |
| ; PTX82-NEXT: } // callseq 1 |
| ; PTX82-NEXT: st.global.b32 [%rd3], %r1; |
| ; PTX82-NEXT: ret; |
| ; |
| ; PTX83-LABEL: kernel_pass_param_ref( |
| ; PTX83: { |
| ; PTX83-NEXT: .reg .b32 %r<2>; |
| ; PTX83-NEXT: .reg .b64 %rd<4>; |
| ; PTX83-EMPTY: |
| ; PTX83-NEXT: // %bb.0: |
| ; PTX83-NEXT: mov.b64 %rd1, kernel_pass_param_ref_param_0; |
| ; PTX83-NEXT: ld.param::entry.b64 %rd2, [kernel_pass_param_ref_param_1]; |
| ; PTX83-NEXT: cvta.to.global.u64 %rd3, %rd2; |
| ; PTX83-NEXT: { // callseq 1, 0 |
| ; PTX83-NEXT: .param .b64 param0; |
| ; PTX83-NEXT: .param .b32 retval0; |
| ; PTX83-NEXT: st.param::func.b64 [param0], %rd1; |
| ; PTX83-NEXT: call.uni (retval0), callee_entry_param, (param0); |
| ; PTX83-NEXT: ld.param::func.b32 %r1, [retval0]; |
| ; PTX83-NEXT: } // callseq 1 |
| ; PTX83-NEXT: st.global.b32 [%rd3], %r1; |
| ; PTX83-NEXT: ret; |
| %p = addrspacecast ptr %input to ptr addrspace(101) |
| %ret = call i32 @callee_entry_param(ptr addrspace(101) %p) |
| store i32 %ret, ptr %out |
| ret void |
| } |