Index: llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h +++ 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; Index: llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp +++ 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); Index: llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/hsa-metadata-deduce-ro-arg.ll +++ 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 @@ -10,7 +10,8 @@ ; CHECK-NEXT: .size: 8 ; CHECK-NEXT: .type_name: 'float*' ; CHECK-NEXT: .value_kind: global_buffer -; CHECK-NEXT: - .address_space: global +; CHECK-NEXT: - .actual_access: write_only +; CHECK-NEXT: .address_space: global ; CHECK-NEXT: .name: out ; CHECK-NEXT: .offset: 8 ; CHECK-NEXT: .size: 8 @@ -19,7 +20,7 @@ ; CHECK: .name: test_ro_arg ; CHECK: .symbol: test_ro_arg.kd -define amdgpu_kernel void @test_ro_arg(ptr addrspace(1) noalias readonly %in, ptr addrspace(1) %out) +define amdgpu_kernel void @test_ro_arg(ptr addrspace(1) noalias readonly %in, ptr addrspace(1) noalias writeonly %out) !kernel_arg_addr_space !0 !kernel_arg_access_qual !1 !kernel_arg_type !2 !kernel_arg_base_type !2 !kernel_arg_type_qual !3 { ret void