Skip to content

Commit

Permalink
[SPV-IR to OCL] Fix mutated builtin call attribute copying (#2208)
Browse files Browse the repository at this point in the history
* [SPV-IR to OCL] Fix mutated builtin call attribute copying

When SPIRVToOCL20Pass translates following SPV IR
```
  %call = tail call spir_func noundef ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi(ptr addrspace(4) noundef %Ptr, i32 noundef 0)
declare spir_func ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi(ptr addrspace(4), i32)
```
to OCL IR:
```
  %call = tail call spir_func noundef ptr @__to_private(ptr addrspace(4) noundef %Ptr)
declare spir_func ptr @__to_private(ptr addrspace(4))
```
, there is error `Attribute after last parameter` at copying attribute
to the new call because the old call has an additional AttributeSet for
the last argument. The last argument is eliminated.

Set tail call for new call if old call is tail call.

Revert cafd7e0.
  • Loading branch information
wenju-he authored Feb 5, 2024
1 parent e329f28 commit a31a0a6
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 22 deletions.
40 changes: 19 additions & 21 deletions lib/SPIRV/SPIRVBuiltinHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ BuiltinCallMutator::BuiltinCallMutator(
CallInst *CI, std::string FuncName, ManglingRules Rules,
std::function<std::string(StringRef)> NameMapFn)
: CI(CI), FuncName(FuncName),
Attrs(CI->getCalledFunction()->getAttributes()), ReturnTy(CI->getType()),
Args(CI->args()), Rules(Rules), Builder(CI) {
Attrs(CI->getCalledFunction()->getAttributes()),
CallAttrs(CI->getAttributes()), ReturnTy(CI->getType()), Args(CI->args()),
Rules(Rules), Builder(CI) {
bool DidDemangle = getParameterTypes(CI->getCalledFunction(), PointerTypes,
std::move(NameMapFn));
if (!DidDemangle) {
Expand All @@ -78,8 +79,8 @@ BuiltinCallMutator::BuiltinCallMutator(
BuiltinCallMutator::BuiltinCallMutator(BuiltinCallMutator &&Other)
: CI(Other.CI), FuncName(std::move(Other.FuncName)),
MutateRet(std::move(Other.MutateRet)), Attrs(Other.Attrs),
ReturnTy(Other.ReturnTy), Args(std::move(Other.Args)),
PointerTypes(std::move(Other.PointerTypes)),
CallAttrs(Other.CallAttrs), ReturnTy(Other.ReturnTy),
Args(std::move(Other.Args)), PointerTypes(std::move(Other.PointerTypes)),
Rules(std::move(Other.Rules)), Builder(CI) {
// Clear the other's CI instance so that it knows not to construct the actual
// call.
Expand All @@ -103,6 +104,8 @@ Value *BuiltinCallMutator::doConversion() {
Builder.Insert(addCallInst(CI->getModule(), FuncName, ReturnTy, Args,
&Attrs, nullptr, Mangler.get()));
NewCall->copyMetadata(*CI);
NewCall->setAttributes(CallAttrs);
NewCall->setTailCall(CI->isTailCall());
if (CI->hasFnAttr("fpbuiltin-max-error")) {
auto Attr = CI->getFnAttr("fpbuiltin-max-error");
NewCall->addFnAttr(Attr);
Expand All @@ -121,6 +124,8 @@ BuiltinCallMutator &BuiltinCallMutator::setArgs(ArrayRef<Value *> NewArgs) {
// Retain only the function attributes, not any parameter attributes.
Attrs = AttributeList::get(CI->getContext(), Attrs.getFnAttrs(),
Attrs.getRetAttrs(), {});
CallAttrs = AttributeList::get(CI->getContext(), CallAttrs.getFnAttrs(),
CallAttrs.getRetAttrs(), {});
Args.clear();
PointerTypes.clear();
for (Value *Arg : NewArgs) {
Expand Down Expand Up @@ -174,6 +179,8 @@ BuiltinCallMutator &BuiltinCallMutator::insertArg(unsigned Index,
PointerTypes.insert(PointerTypes.begin() + Index, Arg.second);
moveAttributes(CI->getContext(), Attrs, Index, Args.size() - Index,
Index + 1);
moveAttributes(CI->getContext(), CallAttrs, Index, Args.size() - Index,
Index + 1);
return *this;
}

Expand All @@ -182,30 +189,21 @@ BuiltinCallMutator &BuiltinCallMutator::replaceArg(unsigned Index,
Args[Index] = Arg.first;
PointerTypes[Index] = Arg.second;
Attrs = Attrs.removeParamAttributes(CI->getContext(), Index);
CallAttrs = CallAttrs.removeParamAttributes(CI->getContext(), Index);
return *this;
}

BuiltinCallMutator &BuiltinCallMutator::removeArg(unsigned Index) {
// If the argument being dropped is the last one, there is nothing to move, so
// just remove the attributes.
auto &Ctx = CI->getContext();
if (Index == Args.size() - 1) {
// TODO: Remove this workaround when LLVM fixes
// https://github.com/llvm/llvm-project/issues/59746 on
// AttributeList::removeParamAttributes function.
// AttributeList::removeParamAttributes function sets attribute at
// specified index empty so that return value of
// AttributeList::getNumAttrSet() keeps unchanged after that call. When call
// BuiltinCallMutator::removeArg function, there is assert failure on
// BuiltinCallMutator::doConversion() since new CallInst removed arg but
// still holds attribute of that removed arg.
SmallVector<AttributeSet, 4> ArgAttrs;
for (unsigned I = 0; I < Index; ++I)
ArgAttrs.push_back(Attrs.getParamAttrs(I));
Attrs = AttributeList::get(CI->getContext(), Attrs.getFnAttrs(),
Attrs.getRetAttrs(), ArgAttrs);
} else
moveAttributes(CI->getContext(), Attrs, Index + 1, Args.size() - Index - 1,
Index);
Attrs = Attrs.removeParamAttributes(Ctx, Index);
CallAttrs = CallAttrs.removeParamAttributes(Ctx, Index);
} else {
moveAttributes(Ctx, Attrs, Index + 1, Args.size() - Index - 1, Index);
moveAttributes(Ctx, CallAttrs, Index + 1, Args.size() - Index - 1, Index);
}
Args.erase(Args.begin() + Index);
PointerTypes.erase(PointerTypes.begin() + Index);
return *this;
Expand Down
4 changes: 3 additions & 1 deletion lib/SPIRV/SPIRVBuiltinHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ class BuiltinCallMutator {
// the new instruction is created.
std::function<llvm::Value *(llvm::IRBuilder<> &, llvm::CallInst *)> MutateRet;
typedef decltype(MutateRet) MutateRetFuncTy;
// The attribute list for the new call instruction.
// The attribute list for the new called function.
llvm::AttributeList Attrs;
// The attribute list for the new call instruction.
llvm::AttributeList CallAttrs;
// The return type for the new call instruction.
llvm::Type *ReturnTy;
// The arguments for the new call instruction.
Expand Down
17 changes: 17 additions & 0 deletions test/call-attribute.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
; REQUIRES: pass-plugin
; UNSUPPORTED: target={{.*windows.*}}

; RUN: opt %load_spirv_lib -passes=spirv-to-ocl20 %s -S -o - | FileCheck %s

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
target triple = "spir64-unknown-unknown"

define spir_func ptr @_Z41__SYCL_GenericCastToPtrExplicit_ToPrivateIN4sycl3_V16marrayIdLm17EEEEPU3AS0T_Pv(ptr addrspace(4) %ptr) {
entry:
; CHECK: tail call spir_func noundef ptr @__to_private(ptr addrspace(4) noundef %ptr)

%call = tail call spir_func noundef ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi(ptr addrspace(4) noundef %ptr, i32 noundef 0)
ret ptr null
}

declare spir_func ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi(ptr addrspace(4), i32)

0 comments on commit a31a0a6

Please sign in to comment.