diff --git a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h --- a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h @@ -105,8 +105,8 @@ msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign = std::nullopt, StringRef Name = "", StringRef TypeName = "", - StringRef BaseTypeName = "", StringRef AccQual = "", - StringRef TypeQual = ""); + StringRef BaseTypeName = "", StringRef ActAccQual = "", + StringRef AccQual = "", StringRef TypeQual = ""); void emitHiddenKernelArgs(const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) override; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp @@ -714,16 +714,20 @@ if (Node && ArgNo < Node->getNumOperands()) BaseTypeName = cast(Node->getOperand(ArgNo))->getString(); - StringRef AccQual; - if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() && - Arg.hasNoAliasAttr()) { - AccQual = "read_only"; - } else { - Node = Func->getMetadata("kernel_arg_access_qual"); - if (Node && ArgNo < Node->getNumOperands()) - AccQual = cast(Node->getOperand(ArgNo))->getString(); + StringRef ActAccQual; + // Do we really need NoAlias check here? + if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) { + if (Arg.onlyReadsMemory()) + ActAccQual = "read_only"; + else if (Arg.hasAttribute(Attribute::WriteOnly)) + ActAccQual = "write_only"; } + StringRef AccQual; + Node = Func->getMetadata("kernel_arg_access_qual"); + if (Node && ArgNo < Node->getNumOperands()) + AccQual = cast(Node->getOperand(ArgNo))->getString(); + StringRef TypeQual; Node = Func->getMetadata("kernel_arg_type_qual"); if (Node && ArgNo < Node->getNumOperands()) @@ -747,14 +751,15 @@ emitKernelArg(DL, ArgTy, ArgAlign, getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args, - PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual); + PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual, + AccQual, TypeQual); } void MetadataStreamerMsgPackV3::emitKernelArg( const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind, unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign, StringRef Name, StringRef TypeName, StringRef BaseTypeName, - StringRef AccQual, StringRef TypeQual) { + StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) { auto Arg = Args.getDocument()->getMapNode(); if (!Name.empty()) @@ -780,7 +785,8 @@ if (auto AQ = getAccessQualifier(AccQual)) Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true); - // TODO: Emit Arg[".actual_access"]. + if (auto AAQ = getAccessQualifier(ActAccQual)) + Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true); SmallVector SplitTypeQuals; TypeQual.split(SplitTypeQuals, " ", -1, false); diff --git a/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll b/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll --- a/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll +++ b/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll @@ -1,7 +1,7 @@ ; RUN: llc -mtriple=amdgcn-amd-amdhsa -filetype=obj -o - < %s | llvm-readelf --notes - | FileCheck %s ; CHECK: - .args: -; CHECK-NEXT: - .access: read_only +; CHECK-NEXT: - .actual_access: read_only ; CHECK-NEXT: .address_space: global ; CHECK-NEXT: .is_const: true ; CHECK-NEXT: .is_restrict: true diff --git a/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduced-arg-attr.ll b/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduced-arg-attr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/hsa-metadata-deduced-arg-attr.ll @@ -0,0 +1,30 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -filetype=obj -o - < %s | llvm-readelf --notes - | FileCheck %s + +; CHECK: amdhsa.kernels: +; CHECK-NEXT: - .args: +; CHECK-NEXT: - .actual_access: read_only +; CHECK-LABEL: .name: test_noalias_ro_arg +define amdgpu_kernel void @test_noalias_ro_arg(ptr noalias readonly %in) { + ret void +} + +; CHECK: - .args: +; CHECK-NOT: read_only +; CHECK-LABEL: .name: test_only_ro_arg +define amdgpu_kernel void @test_only_ro_arg(ptr readonly %in) { + ret void +} + +; CHECK: - .args: +; CHECK-NEXT: - .actual_access: write_only +; CHECK-LABEL: .name: test_noalias_wo_arg +define amdgpu_kernel void @test_noalias_wo_arg(ptr noalias writeonly %out) { + ret void +} + +; CHECK: - .args: +; CHECK-NOT: write_only +; CHECK-LABEL: .name: test_only_wo_arg +define amdgpu_kernel void @test_only_wo_arg(ptr writeonly %out) { + ret void +}