brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · 3bbc060 Raw
99 lines · plain
1; RUN: llc -mtriple=r600 -mcpu=redwood < %s | FileCheck %s2;3; This test checks that the lds input queue will is empty at the end of4; the ALU clause.5 6; CHECK-LABEL: {{^}}lds_input_queue:7; CHECK: LDS_READ_RET * OQAP8; CHECK-NOT: ALU clause9; CHECK: MOV * T{{[0-9]\.[XYZW]}}, OQAP10 11@local_mem = internal unnamed_addr addrspace(3) global [2 x i32] poison, align 412 13define amdgpu_kernel void @lds_input_queue(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %index) {14entry:15  %0 = getelementptr inbounds [2 x i32], ptr addrspace(3) @local_mem, i32 0, i32 %index16  %1 = load i32, ptr addrspace(3) %017  call void @llvm.r600.group.barrier()18 19  ; This will start a new clause for the vertex fetch20  %2 = load i32, ptr addrspace(1) %in21  %3 = add i32 %1, %222  store i32 %3, ptr addrspace(1) %out23  ret void24}25 26declare void @llvm.r600.group.barrier() nounwind convergent27 28; The machine scheduler does not do proper alias analysis and assumes that29; loads from global values (Note that a global value is different that a30; value from global memory.  A global value is a value that is declared31; outside of a function, it can reside in any address space) alias with32; all other loads.33;34; This is a problem for scheduling the reads from the local data share (lds).35; These reads are implemented using two instructions.  The first copies the36; data from lds into the lds output queue, and the second moves the data from37; the input queue into main memory.  These two instructions don't have to be38; scheduled one after the other, but they do need to be scheduled in the same39; clause.  The aliasing problem mentioned above causes problems when there is a40; load from global memory which immediately follows a load from a global value that41; has been declared in the local memory space:42;43;  %0 = getelementptr inbounds [2 x i32], ptr addrspace(3) @local_mem, i32 0, i32 %index44;  %1 = load i32, ptr addrspace(3) %045;  %2 = load i32, ptr addrspace(1) %in46;47; The instruction selection phase will generate ISA that looks like this:48; %oqap = LDS_READ_RET49; %0 = MOV %oqap50; %1 = VTX_READ_3251; %2 = ADD_INT %1, %052;53; The bottom scheduler will schedule the two ALU instructions first:54;55; UNSCHEDULED:56; %oqap = LDS_READ_RET57; %1 = VTX_READ_3258;59; SCHEDULED:60;61; %0 = MOV %oqap62; %2 = ADD_INT %1, %263;64; The lack of proper aliasing results in the local memory read (LDS_READ_RET)65; to consider the global memory read (VTX_READ_32) has a chain dependency, so66; the global memory read will always be scheduled first.  This will give us a67; final program which looks like this:68;69; Alu clause:70; %oqap = LDS_READ_RET71; VTX clause:72; %1 = VTX_READ_3273; Alu clause:74; %0 = MOV %oqap75; %2 = ADD_INT %1, %276;77; This is an illegal program because the oqap def and use know occur in78; different ALU clauses.79;80; This test checks this scenario and makes sure it doesn't result in an81; illegal program.  For now, we have fixed this issue by merging the82; LDS_READ_RET and MOV together during instruction selection and then83; expanding them after scheduling.  Once the scheduler has better alias84; analysis, we should be able to keep these instructions sparate before85; scheduling.86;87; CHECK-LABEL: {{^}}local_global_alias:88; CHECK: LDS_READ_RET89; CHECK-NOT: ALU clause90; CHECK: MOV * T{{[0-9]\.[XYZW]}}, OQAP91define amdgpu_kernel void @local_global_alias(ptr addrspace(1) %out, ptr addrspace(1) %in) {92entry:93  %0 = load i32, ptr addrspace(3) @local_mem94  %1 = load i32, ptr addrspace(1) %in95  %2 = add i32 %1, %096  store i32 %2, ptr addrspace(1) %out97  ret void98}99