2013-11-15 00:12:45 +00:00
|
|
|
; RUN: llc < %s -march=r600 -mcpu=redwood -verify-machineinstrs | FileCheck %s
|
|
|
|
;
|
|
|
|
; This test checks that the lds input queue will is empty at the end of
|
|
|
|
; the ALU clause.
|
|
|
|
|
2014-10-01 17:15:17 +00:00
|
|
|
; CHECK-LABEL: {{^}}lds_input_queue:
|
2013-11-15 00:12:45 +00:00
|
|
|
; CHECK: LDS_READ_RET * OQAP
|
|
|
|
; CHECK-NOT: ALU clause
|
|
|
|
; CHECK: MOV * T{{[0-9]\.[XYZW]}}, OQAP
|
|
|
|
|
2014-11-13 19:56:13 +00:00
|
|
|
@local_mem = internal unnamed_addr addrspace(3) global [2 x i32] undef, align 4
|
2013-11-15 00:12:45 +00:00
|
|
|
|
|
|
|
define void @lds_input_queue(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %index) {
|
|
|
|
entry:
|
[opaque pointer type] Add textual IR support for explicit type parameter to getelementptr instruction
One of several parallel first steps to remove the target type of pointers,
replacing them with a single opaque pointer type.
This adds an explicit type parameter to the gep instruction so that when the
first parameter becomes an opaque pointer type, the type to gep through is
still available to the instructions.
* This doesn't modify gep operators, only instructions (operators will be
handled separately)
* Textual IR changes only. Bitcode (including upgrade) and changing the
in-memory representation will be in separate changes.
* geps of vectors are transformed as:
getelementptr <4 x float*> %x, ...
->getelementptr float, <4 x float*> %x, ...
Then, once the opaque pointer type is introduced, this will ultimately look
like:
getelementptr float, <4 x ptr> %x
with the unambiguous interpretation that it is a vector of pointers to float.
* address spaces remain on the pointer, not the type:
getelementptr float addrspace(1)* %x
->getelementptr float, float addrspace(1)* %x
Then, eventually:
getelementptr float, ptr addrspace(1) %x
Importantly, the massive amount of test case churn has been automated by
same crappy python code. I had to manually update a few test cases that
wouldn't fit the script's model (r228970,r229196,r229197,r229198). The
python script just massages stdin and writes the result to stdout, I
then wrapped that in a shell script to handle replacing files, then
using the usual find+xargs to migrate all the files.
update.py:
import fileinput
import sys
import re
ibrep = re.compile(r"(^.*?[^%\w]getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
normrep = re.compile( r"(^.*?[^%\w]getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
def conv(match, line):
if not match:
return line
line = match.groups()[0]
if len(match.groups()[5]) == 0:
line += match.groups()[2]
line += match.groups()[3]
line += ", "
line += match.groups()[1]
line += "\n"
return line
for line in sys.stdin:
if line.find("getelementptr ") == line.find("getelementptr inbounds"):
if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("):
line = conv(re.match(ibrep, line), line)
elif line.find("getelementptr ") != line.find("getelementptr ("):
line = conv(re.match(normrep, line), line)
sys.stdout.write(line)
apply.sh:
for name in "$@"
do
python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name"
rm -f "$name.tmp"
done
The actual commands:
From llvm/src:
find test/ -name *.ll | xargs ./apply.sh
From llvm/src/tools/clang:
find test/ -name *.mm -o -name *.m -o -name *.cpp -o -name *.c | xargs -I '{}' ../../apply.sh "{}"
From llvm/src/tools/polly:
find test/ -name *.ll | xargs ./apply.sh
After that, check-all (with llvm, clang, clang-tools-extra, lld,
compiler-rt, and polly all checked out).
The extra 'rm' in the apply.sh script is due to a few files in clang's test
suite using interesting unicode stuff that my python script was throwing
exceptions on. None of those files needed to be migrated, so it seemed
sufficient to ignore those cases.
Reviewers: rafael, dexonsmith, grosser
Differential Revision: http://reviews.llvm.org/D7636
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230786 91177308-0d34-0410-b5e6-96231b3b80d8
2015-02-27 19:29:02 +00:00
|
|
|
%0 = getelementptr inbounds [2 x i32], [2 x i32] addrspace(3)* @local_mem, i32 0, i32 %index
|
2015-02-27 21:17:42 +00:00
|
|
|
%1 = load i32, i32 addrspace(3)* %0
|
2013-11-15 00:12:45 +00:00
|
|
|
call void @llvm.AMDGPU.barrier.local()
|
|
|
|
|
|
|
|
; This will start a new clause for the vertex fetch
|
2015-02-27 21:17:42 +00:00
|
|
|
%2 = load i32, i32 addrspace(1)* %in
|
2013-11-15 00:12:45 +00:00
|
|
|
%3 = add i32 %1, %2
|
|
|
|
store i32 %3, i32 addrspace(1)* %out
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
declare void @llvm.AMDGPU.barrier.local()
|
|
|
|
|
|
|
|
; The machine scheduler does not do proper alias analysis and assumes that
|
|
|
|
; loads from global values (Note that a global value is different that a
|
|
|
|
; value from global memory. A global value is a value that is declared
|
|
|
|
; outside of a function, it can reside in any address space) alias with
|
|
|
|
; all other loads.
|
|
|
|
;
|
|
|
|
; This is a problem for scheduling the reads from the local data share (lds).
|
|
|
|
; These reads are implemented using two instructions. The first copies the
|
|
|
|
; data from lds into the lds output queue, and the second moves the data from
|
|
|
|
; the input queue into main memory. These two instructions don't have to be
|
|
|
|
; scheduled one after the other, but they do need to be scheduled in the same
|
|
|
|
; clause. The aliasing problem mentioned above causes problems when there is a
|
|
|
|
; load from global memory which immediately follows a load from a global value that
|
|
|
|
; has been declared in the local memory space:
|
|
|
|
;
|
[opaque pointer type] Add textual IR support for explicit type parameter to getelementptr instruction
One of several parallel first steps to remove the target type of pointers,
replacing them with a single opaque pointer type.
This adds an explicit type parameter to the gep instruction so that when the
first parameter becomes an opaque pointer type, the type to gep through is
still available to the instructions.
* This doesn't modify gep operators, only instructions (operators will be
handled separately)
* Textual IR changes only. Bitcode (including upgrade) and changing the
in-memory representation will be in separate changes.
* geps of vectors are transformed as:
getelementptr <4 x float*> %x, ...
->getelementptr float, <4 x float*> %x, ...
Then, once the opaque pointer type is introduced, this will ultimately look
like:
getelementptr float, <4 x ptr> %x
with the unambiguous interpretation that it is a vector of pointers to float.
* address spaces remain on the pointer, not the type:
getelementptr float addrspace(1)* %x
->getelementptr float, float addrspace(1)* %x
Then, eventually:
getelementptr float, ptr addrspace(1) %x
Importantly, the massive amount of test case churn has been automated by
same crappy python code. I had to manually update a few test cases that
wouldn't fit the script's model (r228970,r229196,r229197,r229198). The
python script just massages stdin and writes the result to stdout, I
then wrapped that in a shell script to handle replacing files, then
using the usual find+xargs to migrate all the files.
update.py:
import fileinput
import sys
import re
ibrep = re.compile(r"(^.*?[^%\w]getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
normrep = re.compile( r"(^.*?[^%\w]getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
def conv(match, line):
if not match:
return line
line = match.groups()[0]
if len(match.groups()[5]) == 0:
line += match.groups()[2]
line += match.groups()[3]
line += ", "
line += match.groups()[1]
line += "\n"
return line
for line in sys.stdin:
if line.find("getelementptr ") == line.find("getelementptr inbounds"):
if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("):
line = conv(re.match(ibrep, line), line)
elif line.find("getelementptr ") != line.find("getelementptr ("):
line = conv(re.match(normrep, line), line)
sys.stdout.write(line)
apply.sh:
for name in "$@"
do
python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name"
rm -f "$name.tmp"
done
The actual commands:
From llvm/src:
find test/ -name *.ll | xargs ./apply.sh
From llvm/src/tools/clang:
find test/ -name *.mm -o -name *.m -o -name *.cpp -o -name *.c | xargs -I '{}' ../../apply.sh "{}"
From llvm/src/tools/polly:
find test/ -name *.ll | xargs ./apply.sh
After that, check-all (with llvm, clang, clang-tools-extra, lld,
compiler-rt, and polly all checked out).
The extra 'rm' in the apply.sh script is due to a few files in clang's test
suite using interesting unicode stuff that my python script was throwing
exceptions on. None of those files needed to be migrated, so it seemed
sufficient to ignore those cases.
Reviewers: rafael, dexonsmith, grosser
Differential Revision: http://reviews.llvm.org/D7636
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230786 91177308-0d34-0410-b5e6-96231b3b80d8
2015-02-27 19:29:02 +00:00
|
|
|
; %0 = getelementptr inbounds [2 x i32], [2 x i32] addrspace(3)* @local_mem, i32 0, i32 %index
|
2015-02-27 21:17:42 +00:00
|
|
|
; %1 = load i32, i32 addrspace(3)* %0
|
|
|
|
; %2 = load i32, i32 addrspace(1)* %in
|
2013-11-15 00:12:45 +00:00
|
|
|
;
|
|
|
|
; The instruction selection phase will generate ISA that looks like this:
|
|
|
|
; %OQAP = LDS_READ_RET
|
|
|
|
; %vreg0 = MOV %OQAP
|
|
|
|
; %vreg1 = VTX_READ_32
|
|
|
|
; %vreg2 = ADD_INT %vreg1, %vreg0
|
|
|
|
;
|
|
|
|
; The bottom scheduler will schedule the two ALU instructions first:
|
|
|
|
;
|
|
|
|
; UNSCHEDULED:
|
|
|
|
; %OQAP = LDS_READ_RET
|
|
|
|
; %vreg1 = VTX_READ_32
|
|
|
|
;
|
|
|
|
; SCHEDULED:
|
|
|
|
;
|
|
|
|
; vreg0 = MOV %OQAP
|
|
|
|
; vreg2 = ADD_INT %vreg1, %vreg2
|
|
|
|
;
|
|
|
|
; The lack of proper aliasing results in the local memory read (LDS_READ_RET)
|
|
|
|
; to consider the global memory read (VTX_READ_32) has a chain dependency, so
|
|
|
|
; the global memory read will always be scheduled first. This will give us a
|
|
|
|
; final program which looks like this:
|
|
|
|
;
|
|
|
|
; Alu clause:
|
|
|
|
; %OQAP = LDS_READ_RET
|
|
|
|
; VTX clause:
|
|
|
|
; %vreg1 = VTX_READ_32
|
|
|
|
; Alu clause:
|
|
|
|
; vreg0 = MOV %OQAP
|
|
|
|
; vreg2 = ADD_INT %vreg1, %vreg2
|
|
|
|
;
|
|
|
|
; This is an illegal program because the OQAP def and use know occur in
|
|
|
|
; different ALU clauses.
|
|
|
|
;
|
|
|
|
; This test checks this scenario and makes sure it doesn't result in an
|
|
|
|
; illegal program. For now, we have fixed this issue by merging the
|
|
|
|
; LDS_READ_RET and MOV together during instruction selection and then
|
|
|
|
; expanding them after scheduling. Once the scheduler has better alias
|
|
|
|
; analysis, we should be able to keep these instructions sparate before
|
|
|
|
; scheduling.
|
|
|
|
;
|
2014-10-01 17:15:17 +00:00
|
|
|
; CHECK-LABEL: {{^}}local_global_alias:
|
2013-11-15 00:12:45 +00:00
|
|
|
; CHECK: LDS_READ_RET
|
|
|
|
; CHECK-NOT: ALU clause
|
2014-01-11 21:06:00 +00:00
|
|
|
; CHECK: MOV * T{{[0-9]\.[XYZW]}}, OQAP
|
2013-11-15 00:12:45 +00:00
|
|
|
define void @local_global_alias(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
|
|
|
|
entry:
|
[opaque pointer type] Add textual IR support for explicit type parameter to getelementptr instruction
One of several parallel first steps to remove the target type of pointers,
replacing them with a single opaque pointer type.
This adds an explicit type parameter to the gep instruction so that when the
first parameter becomes an opaque pointer type, the type to gep through is
still available to the instructions.
* This doesn't modify gep operators, only instructions (operators will be
handled separately)
* Textual IR changes only. Bitcode (including upgrade) and changing the
in-memory representation will be in separate changes.
* geps of vectors are transformed as:
getelementptr <4 x float*> %x, ...
->getelementptr float, <4 x float*> %x, ...
Then, once the opaque pointer type is introduced, this will ultimately look
like:
getelementptr float, <4 x ptr> %x
with the unambiguous interpretation that it is a vector of pointers to float.
* address spaces remain on the pointer, not the type:
getelementptr float addrspace(1)* %x
->getelementptr float, float addrspace(1)* %x
Then, eventually:
getelementptr float, ptr addrspace(1) %x
Importantly, the massive amount of test case churn has been automated by
same crappy python code. I had to manually update a few test cases that
wouldn't fit the script's model (r228970,r229196,r229197,r229198). The
python script just massages stdin and writes the result to stdout, I
then wrapped that in a shell script to handle replacing files, then
using the usual find+xargs to migrate all the files.
update.py:
import fileinput
import sys
import re
ibrep = re.compile(r"(^.*?[^%\w]getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
normrep = re.compile( r"(^.*?[^%\w]getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
def conv(match, line):
if not match:
return line
line = match.groups()[0]
if len(match.groups()[5]) == 0:
line += match.groups()[2]
line += match.groups()[3]
line += ", "
line += match.groups()[1]
line += "\n"
return line
for line in sys.stdin:
if line.find("getelementptr ") == line.find("getelementptr inbounds"):
if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("):
line = conv(re.match(ibrep, line), line)
elif line.find("getelementptr ") != line.find("getelementptr ("):
line = conv(re.match(normrep, line), line)
sys.stdout.write(line)
apply.sh:
for name in "$@"
do
python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name"
rm -f "$name.tmp"
done
The actual commands:
From llvm/src:
find test/ -name *.ll | xargs ./apply.sh
From llvm/src/tools/clang:
find test/ -name *.mm -o -name *.m -o -name *.cpp -o -name *.c | xargs -I '{}' ../../apply.sh "{}"
From llvm/src/tools/polly:
find test/ -name *.ll | xargs ./apply.sh
After that, check-all (with llvm, clang, clang-tools-extra, lld,
compiler-rt, and polly all checked out).
The extra 'rm' in the apply.sh script is due to a few files in clang's test
suite using interesting unicode stuff that my python script was throwing
exceptions on. None of those files needed to be migrated, so it seemed
sufficient to ignore those cases.
Reviewers: rafael, dexonsmith, grosser
Differential Revision: http://reviews.llvm.org/D7636
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230786 91177308-0d34-0410-b5e6-96231b3b80d8
2015-02-27 19:29:02 +00:00
|
|
|
%0 = getelementptr inbounds [2 x i32], [2 x i32] addrspace(3)* @local_mem, i32 0, i32 0
|
2015-02-27 21:17:42 +00:00
|
|
|
%1 = load i32, i32 addrspace(3)* %0
|
|
|
|
%2 = load i32, i32 addrspace(1)* %in
|
2013-11-15 00:12:45 +00:00
|
|
|
%3 = add i32 %2, %1
|
|
|
|
store i32 %3, i32 addrspace(1)* %out
|
|
|
|
ret void
|
|
|
|
}
|