Skip to content
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

[OpenCL] Fix an infinite loop in builidng AddrSpaceQualType #92612

Merged
merged 3 commits into from
May 20, 2024

Conversation

changpeng
Copy link
Contributor

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.

 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.
@changpeng changpeng requested a review from svenvh May 17, 2024 22:17
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen labels May 17, 2024
@llvmbot
Copy link
Member

llvmbot commented May 17, 2024

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Changpeng Fang (changpeng)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/92612.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGExprAgg.cpp (+2-1)
  • (added) clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp (+25)
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 6172eb9cdc1bb..53ce133e8cbc6 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -537,8 +537,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
       elementType.isTriviallyCopyableType(CGF.getContext())) {
     CodeGen::CodeGenModule &CGM = CGF.CGM;
     ConstantEmitter Emitter(CGF);
+    Qualifiers Quals;
     QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType(
-        CGM.getContext().removeAddrSpaceQualType(ArrayQTy),
+        CGM.getContext().getUnqualifiedArrayType(ArrayQTy, Quals),
         CGM.GetGlobalConstantAddressSpace());
     LangAS AS = GVArrayQTy.getAddressSpace();
     if (llvm::Constant *C =
diff --git a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp
new file mode 100644
index 0000000000000..5a5b104e892f7
--- /dev/null
+++ b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp
@@ -0,0 +1,25 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+//RUN: %clang_cc1 %s -emit-llvm -O1 -o - | FileCheck %s
+
+// CHECK-LABEL: define dso_local spir_kernel void @test(
+// CHECK-SAME: ptr nocapture noundef readonly align 8 [[IN:%.*]], ptr nocapture noundef writeonly align 8 [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[ARRAYIDX1]], align 8, !tbaa [[TBAA7:![0-9]+]]
+// CHECK-NEXT:    store i64 [[TMP0]], ptr [[OUT]], align 8, !tbaa [[TBAA7]]
+// CHECK-NEXT:    ret void
+//
+__kernel void test(__global long *In, __global long *Out) {
+   long m[4] = {  In[0], In[1], 0, 0 };
+   *Out = m[1];
+}
+//.
+// CHECK: [[META3]] = !{i32 1, i32 1}
+// CHECK: [[META4]] = !{!"none", !"none"}
+// CHECK: [[META5]] = !{!"long*", !"long*"}
+// CHECK: [[META6]] = !{!"", !""}
+// CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
+// CHECK: [[META8]] = !{!"long", [[META9:![0-9]+]], i64 0}
+// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0}
+// CHECK: [[META10]] = !{!"Simple C++ TBAA"}
+//.

QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType(
CGM.getContext().removeAddrSpaceQualType(ArrayQTy),
CGM.getContext().getUnqualifiedArrayType(ArrayQTy, Quals),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see two issues with this fix:

  1. It leaves removeAddrSpaceQualType broken for anyone else who tries to use it. Ideally, removeAddrSpaceQualType should do what it says.
  2. This drops other qualifiers on the floor; they might be relevant in some cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean we should actually fix removeAddrSpaceQualType? Somewhere inside removeAddrSpaceQualType, we
should use getUnqualifiedArrayType if it is an arrayType, and getSingleStepDesugaredType othereise?
I have to admit that I have no experience in this field, so I am relying on you and @svenvh to move on for a reasonable fix. Thanks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that, yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that, yes.

Thanks. Updated. Should be closer!

  Fix ASTContext::removeAddrSpaceQualType()
@llvmbot llvmbot added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label May 18, 2024
@@ -0,0 +1,25 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
//RUN: %clang_cc1 %s -emit-llvm -O1 -o - | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codegen tests need an explicit target

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add "triple spir", same as other tests in the same directory

// array type
if (T.getTypePtr()->isArrayType()) {
Qualifiers Qualfs;
return getUnqualifiedArrayType(T, Qualfs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to preserve the non-address-space qualifiers, the same way the code after the loop does. Actually, I'd just recommend restructuring to use the existing code, something like:

if (T.getTypePtr()->isArrayType()) {
  getUnqualifiedArrayType()
} else {
  while (T.hasAddressSpace()) {
     [...]
  }
}

Copy link
Contributor Author

@changpeng changpeng May 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Can I do as the following?
Note that I am passing QualifierCollector to getUnqualifiedArrayType, which has Qualifiers as the second argument.
Also, TypeNode = T.getTypePtr(); after I is unqualified.

QualifierCollector Quals;
const Type *TypeNode;
if (T.getTypePtr()->isArrayType()) {
T = getUnqualifiedArrayType(T, Quals);
TypeNode = T.getTypePtr();
} else {
while (T.hasAddressSpace()) {
....

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@changpeng changpeng merged commit 753f7e8 into llvm:main May 20, 2024
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants