-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[OpenCL] Put constant initializer globals into constant addrspace #90048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Place constant initializer globals into the constant address space. Clang generates such globals for e.g. larger array member initializers of classes and then emits copy operations from the global to the object(s). The globals are never written so they ought to be in the constant address space.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Sven van Haastregt (svenvh) ChangesPlace constant initializer globals into the constant address space. Clang generates such globals for e.g. larger array member initializers of classes and then emits copy operations from the global to the object(s). The globals are never written so they ought to be in the constant address space. Full diff: https://github.com/llvm/llvm-project/pull/90048.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 355fec42be4489..30cde245cc837c 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -536,6 +536,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
CodeGen::CodeGenModule &CGM = CGF.CGM;
ConstantEmitter Emitter(CGF);
LangAS AS = ArrayQTy.getAddressSpace();
+ if (CGF.getLangOpts().OpenCL)
+ AS = LangAS::opencl_constant;
if (llvm::Constant *C =
Emitter.tryEmitForInitializer(ExprToVisit, AS, ArrayQTy)) {
auto GV = new llvm::GlobalVariable(
diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.clcpp b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.clcpp
index 18d97a989a4364..a0ed03b25535c8 100644
--- a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.clcpp
+++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.clcpp
@@ -5,7 +5,7 @@
// for constructors, member functions and destructors.
// See also atexit.cl and global_init.cl for other specific tests.
-// CHECK: %struct.MyType = type { i32 }
+// CHECK: %struct.MyType = type { i32, [5 x i32] }
struct MyType {
MyType(int i) : i(i) {}
MyType(int i) __constant : i(i) {}
@@ -14,6 +14,7 @@ struct MyType {
int bar() { return i + 2; }
int bar() __constant { return i + 1; }
int i;
+ int a[5] = {42, 43, 44, 45, 46};
};
// CHECK: @const1 ={{.*}} addrspace(2) global %struct.MyType zeroinitializer
@@ -23,6 +24,8 @@ __constant MyType const2(2);
// CHECK: @glob ={{.*}} addrspace(1) global %struct.MyType zeroinitializer
MyType glob(1);
+// CHECK: @constinit ={{.*}} addrspace(2) constant [5 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46]
+
// CHECK: call spir_func void @_ZNU3AS26MyTypeC1Ei(ptr addrspace(2) {{[^,]*}} @const1, i32 noundef 1)
// CHECK: call spir_func void @_ZNU3AS26MyTypeC1Ei(ptr addrspace(2) {{[^,]*}} @const2, i32 noundef 2)
// CHECK: call spir_func void @_ZNU3AS46MyTypeC1Ei(ptr addrspace(4) {{[^,]*}} addrspacecast (ptr addrspace(1) @glob to ptr addrspace(4)), i32 noundef 1)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -535,20 +535,23 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, | |||
elementType.isTriviallyCopyableType(CGF.getContext())) { | |||
CodeGen::CodeGenModule &CGM = CGF.CGM; | |||
ConstantEmitter Emitter(CGF); | |||
LangAS AS = ArrayQTy.getAddressSpace(); | |||
QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType( | |||
CGM.getContext().removeAddrSpaceQualType(ArrayQTy), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We saw a regression caused by this PR. It is a soft hang in CGM.getContext().removeAddrSpaceQualType.
Specifically it is in the following while loop:
while (T.hasAddressSpace()) {
TypeNode = Quals.strip(T);
// If the type no longer has an address space after stripping qualifiers,
// jump out.
if (!QualType(TypeNode, 0).hasAddressSpace())
break;
// There might be sugar in the way. Strip it and try again.
T = T.getSingleStepDesugaredType(*this);
}
We found that "T == T.getSingleStepDesugaredType(*this);" and this it could not proceed.
I am not sure whether we should break out this loop when "T == T.getSingleStepDesugaredType(*this)"
or something else is wrong that we should never see such case.
Here is the dump of T:
ConstantArrayType 0x555565b40640 '__private ulong[16]' 16
-QualType 0x555565b403f8 '__private ulong' __private
-ElaboratedType 0x555565b3ff40 'ulong' sugar imported
-TypedefType 0x555565b3fef0 'ulong' sugar imported |-Typedef 0x555565b3fe80 'ulong'
-BuiltinType 0x55556583f430 'unsigned long'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a bug in removeAddrSpaceQualType(): it needs to special-case arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. So it needs to strip the qualifier off the element type, then reconstruct the array type. Maybe it can use ASTContext::getUnqualifiedArrayType.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@changpeng would you be able to provide an input source that demonstrates the issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a bug in removeAddrSpaceQualType(): it needs to special-case arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. So it needs to strip the qualifier off the element type, then reconstruct the array type. Maybe it can use ASTC
getSingleStepDesugaredType
Yes, the issue is in removeAddrSpaceQualType(ArrayQTy), And getSingleStepDesugaredType can not remove "Sugar".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@changpeng would you be able to provide an input source that demonstrates the issue?
Hi, @svenvh : I attached test.cl.txt here which is the dumped opencl source file. Unfortunately I do not know exactly how to reproduce the infinite loop offline with this source. I extracted out the following simplified kernel which can reproduce the hang with
clang -c -Xclang -emit-llvm -O0 test.clcpp
__kernel void nonceGrind(__global ulong *headerIn, __global ulong *nonceOut) {
ulong m[16] = { headerIn[0], headerIn[1],
headerIn[2], headerIn[3],
0, headerIn[5],
headerIn[6], headerIn[7],
headerIn[8], headerIn[9], 0, 0, 0, 0, 0, 0 };
*nonceOut = m[4];
}
However, I am afraid it may not fully represent the original issue. This is because after I break out the loop in
ASTContext::removeAddrSpaceQualType, I am seeing the following assert:
clang: /home/chfang/llvm-project/clang/include/clang/AST/Type.h:677: void clang::Qualifiers::addConsistentQualifiers(Qualifiers): Assertion `getAddressSpace() == qs.getAddressSpace() || !hasAddressSpace() || !qs.hasAddressSpace()' failed.
Hopefully the information is useful, and you are able to help. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reduced further:
clang -c -Xclang -emit-llvm -O0 test.clcpp
__kernel void test(__global ulong *In, __global ulong *Out) {
ulong m[4] = { In[0], In[1], 0, 0 };
*Out = m[1];
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a bug in removeAddrSpaceQualType(): it needs to special-case arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. So it needs to strip the qualifier off the element type, then reconstruct the array type. Maybe it can use ASTContext::getUnqualifiedArrayType.
Thanks for the suggestion. I drafted a fix:
#92612
In building AddrSpaceQualType (llvm#90048), there is a bug in removeAddrSpaceQualType() for arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. This results in an infinite loop in removeAddrSpaceQualType. To fix the issue, we use ASTContext::getUnqualifiedArrayType, which strips the qualifier off the element type, then reconstruct the array type.
In building AddrSpaceQualType (#90048), there is a bug in removeAddrSpaceQualType() for arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. This results in an infinite loop in removeAddrSpaceQualType. To fix the issue, we use ASTContext::getUnqualifiedArrayType instead, which strips the qualifier off the element type, then reconstruct the array type.
Place constant initializer globals into the constant address space. Clang generates such globals for e.g. larger array member initializers of classes and then emits copy operations from the global to the object(s). The globals are never written so they ought to be in the constant address space.