-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[SPIR-V] Cast ptr kernel args to i8* when used as Store's value operand #78603
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
//===--- SPIRVMetadata.cpp ---- IR Metadata Parsing Funcs -------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file contains functions needed for parsing LLVM IR metadata relevant | ||
// to the SPIR-V target. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "SPIRVMetadata.h" | ||
|
||
using namespace llvm; | ||
|
||
static MDString *getOCLKernelArgAttribute(const Function &F, unsigned ArgIdx, | ||
const StringRef AttributeName) { | ||
assert( | ||
F.getCallingConv() == CallingConv::SPIR_KERNEL && | ||
"Kernel attributes are attached/belong only to OpenCL kernel functions"); | ||
|
||
// Lookup the argument attribute in metadata attached to the kernel function. | ||
MDNode *Node = F.getMetadata(AttributeName); | ||
if (Node && ArgIdx < Node->getNumOperands()) | ||
return cast<MDString>(Node->getOperand(ArgIdx)); | ||
|
||
// Sometimes metadata containing kernel attributes is not attached to the | ||
// function, but can be found in the named module-level metadata instead. | ||
// For example: | ||
// !opencl.kernels = !{!0} | ||
// !0 = !{void ()* @someKernelFunction, !1, ...} | ||
// !1 = !{!"kernel_arg_addr_space", ...} | ||
// In this case the actual index of searched argument attribute is ArgIdx + 1, | ||
// since the first metadata node operand is occupied by attribute name | ||
// ("kernel_arg_addr_space" in the example above). | ||
unsigned MDArgIdx = ArgIdx + 1; | ||
NamedMDNode *OpenCLKernelsMD = | ||
F.getParent()->getNamedMetadata("opencl.kernels"); | ||
if (!OpenCLKernelsMD || OpenCLKernelsMD->getNumOperands() == 0) | ||
return nullptr; | ||
|
||
// KernelToMDNodeList contains kernel function declarations followed by | ||
// corresponding MDNodes for each attribute. Search only MDNodes "belonging" | ||
// to the currently lowered kernel function. | ||
MDNode *KernelToMDNodeList = OpenCLKernelsMD->getOperand(0); | ||
bool FoundLoweredKernelFunction = false; | ||
for (const MDOperand &Operand : KernelToMDNodeList->operands()) { | ||
ValueAsMetadata *MaybeValue = dyn_cast<ValueAsMetadata>(Operand); | ||
if (MaybeValue && | ||
dyn_cast<Function>(MaybeValue->getValue())->getName() == F.getName()) { | ||
FoundLoweredKernelFunction = true; | ||
continue; | ||
} | ||
if (MaybeValue && FoundLoweredKernelFunction) | ||
return nullptr; | ||
|
||
MDNode *MaybeNode = dyn_cast<MDNode>(Operand); | ||
if (FoundLoweredKernelFunction && MaybeNode && | ||
cast<MDString>(MaybeNode->getOperand(0))->getString() == | ||
AttributeName && | ||
MDArgIdx < MaybeNode->getNumOperands()) | ||
return cast<MDString>(MaybeNode->getOperand(MDArgIdx)); | ||
} | ||
return nullptr; | ||
} | ||
|
||
namespace llvm { | ||
|
||
MDString *getOCLKernelArgAccessQual(const Function &F, unsigned ArgIdx) { | ||
assert( | ||
F.getCallingConv() == CallingConv::SPIR_KERNEL && | ||
"Kernel attributes are attached/belong only to OpenCL kernel functions"); | ||
return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_access_qual"); | ||
} | ||
|
||
MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx) { | ||
assert( | ||
F.getCallingConv() == CallingConv::SPIR_KERNEL && | ||
"Kernel attributes are attached/belong only to OpenCL kernel functions"); | ||
return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type_qual"); | ||
} | ||
|
||
MDString *getOCLKernelArgType(const Function &F, unsigned ArgIdx) { | ||
assert( | ||
F.getCallingConv() == CallingConv::SPIR_KERNEL && | ||
"Kernel attributes are attached/belong only to OpenCL kernel functions"); | ||
return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type"); | ||
} | ||
|
||
} // namespace llvm |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//===--- SPIRVMetadata.h ---- IR Metadata Parsing Funcs ---------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file contains functions needed for parsing LLVM IR metadata relevant | ||
// to the SPIR-V target. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMETADATA_H | ||
#define LLVM_LIB_TARGET_SPIRV_SPIRVMETADATA_H | ||
|
||
#include "llvm/IR/Metadata.h" | ||
#include "llvm/IR/Module.h" | ||
|
||
namespace llvm { | ||
|
||
//===----------------------------------------------------------------------===// | ||
// OpenCL Metadata | ||
// | ||
|
||
MDString *getOCLKernelArgAccessQual(const Function &F, unsigned ArgIdx); | ||
MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx); | ||
MDString *getOCLKernelArgType(const Function &F, unsigned ArgIdx); | ||
|
||
} // namespace llvm | ||
#endif // LLVM_LIB_TARGET_SPIRV_METADATA_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s | ||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} | ||
|
||
; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8 | ||
; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]] | ||
|
||
define spir_kernel void @foo(ptr addrspace(1) %arg) { | ||
ret void | ||
} | ||
|
||
; CHECK: %[[#]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s | ||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} | ||
|
||
; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8 | ||
; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]] | ||
|
||
define spir_kernel void @foo(i8 %a, ptr addrspace(1) %p) { | ||
store i8 %a, ptr addrspace(1) %p | ||
ret void | ||
} | ||
|
||
; CHECK: %[[#A:]] = OpFunctionParameter %[[#CHAR]] | ||
; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]] | ||
; CHECK: OpStore %[[#P]] %[[#A]] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s | ||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} | ||
|
||
; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8 | ||
; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]] | ||
|
||
define spir_kernel void @foo(ptr addrspace(1) %arg) !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_base_type !3 !kernel_arg_type_qual !4 { | ||
%var = alloca ptr addrspace(1), align 8 | ||
; CHECK: %[[#]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]] | ||
; CHECK-NOT: %[[#]] = OpBitcast %[[#]] %[[#]] | ||
store ptr addrspace(1) %arg, ptr %var, align 8 | ||
ret void | ||
} | ||
|
||
!1 = !{i32 1} | ||
!2 = !{!"none"} | ||
!3 = !{!"char*"} | ||
!4 = !{!""} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s | ||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} | ||
|
||
define spir_kernel void @foo(ptr addrspace(1) %arg) !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_base_type !3 !kernel_arg_type_qual !4 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a test that covers the case you mentioned where the arguments can be found in the module-level metadata? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we do have a test in |
||
%var = alloca ptr addrspace(1), align 8 | ||
; CHECK: %[[#VAR:]] = OpVariable %[[#]] Function | ||
store ptr addrspace(1) %arg, ptr %var, align 8 | ||
; The test itends to verify that OpStore uses OpVariable result directly (without a bitcast). | ||
; Other type checking is done by spirv-val. | ||
; CHECK: OpStore %[[#VAR]] %[[#]] Aligned 8 | ||
%lod = load ptr addrspace(1), ptr %var, align 8 | ||
%idx = getelementptr inbounds i64, ptr addrspace(1) %lod, i64 0 | ||
ret void | ||
} | ||
|
||
!1 = !{i32 1} | ||
!2 = !{!"none"} | ||
!3 = !{!"ulong*"} | ||
!4 = !{!""} |
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.
Can Arg be nullptr?
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.
You should be able to safely use
cast<>
here instead ofdyn_cast
since you have theisa
check.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.
Thanks @sudonatalie! Fixed!