diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -21,6 +21,7 @@ #include "SPIRVSubtarget.h" #include "SPIRVUtils.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/Support/ModRef.h" using namespace llvm; @@ -49,19 +50,20 @@ // Based on the LLVM function attributes, get a SPIR-V FunctionControl. static uint32_t getFunctionControl(const Function &F) { + MemoryEffects MemEffects = F.getMemoryEffects(); + uint32_t FuncControl = static_cast(SPIRV::FunctionControl::None); - if (F.hasFnAttribute(Attribute::AttrKind::AlwaysInline)) { + + if (F.hasFnAttribute(Attribute::AttrKind::NoInline)) + FuncControl |= static_cast(SPIRV::FunctionControl::DontInline); + else if (F.hasFnAttribute(Attribute::AttrKind::AlwaysInline)) FuncControl |= static_cast(SPIRV::FunctionControl::Inline); - } - if (F.hasFnAttribute(Attribute::AttrKind::ReadNone)) { + + if (MemEffects.doesNotAccessMemory()) FuncControl |= static_cast(SPIRV::FunctionControl::Pure); - } - if (F.hasFnAttribute(Attribute::AttrKind::ReadOnly)) { + else if (MemEffects.onlyReadsMemory()) FuncControl |= static_cast(SPIRV::FunctionControl::Const); - } - if (F.hasFnAttribute(Attribute::AttrKind::NoInline)) { - FuncControl |= static_cast(SPIRV::FunctionControl::DontInline); - } + return FuncControl; } diff --git a/llvm/test/CodeGen/SPIRV/function/trivial-function-with-attributes.ll b/llvm/test/CodeGen/SPIRV/function/trivial-function-with-attributes.ll --- a/llvm/test/CodeGen/SPIRV/function/trivial-function-with-attributes.ll +++ b/llvm/test/CodeGen/SPIRV/function/trivial-function-with-attributes.ll @@ -10,6 +10,8 @@ ; CHECK-DAG: OpName %[[#FN5:]] "fn5" ; CHECK-DAG: OpName %[[#FN6:]] "fn6" ; CHECK-DAG: OpName %[[#FN7:]] "fn7" +; CHECK-DAG: OpName %[[#FN8:]] "fn8" +; CHECK-DAG: OpName %[[#FN9:]] "fn9" ;; Types: ; CHECK: %[[#VOID:]] = OpTypeVoid @@ -56,15 +58,29 @@ ; CHECK: OpFunctionEnd -define void @fn6() readonly { +define void @fn6() memory(none) { ret void } -; CHECK: %[[#FN6]] = OpFunction %[[#VOID]] Const %[[#FN]] +; CHECK: %[[#FN6]] = OpFunction %[[#VOID]] Pure %[[#FN]] ; CHECK: OpFunctionEnd -define void @fn7() alwaysinline readnone { +define void @fn7() readonly { ret void } -; CHECK: %[[#FN7]] = OpFunction %[[#VOID]] Inline|Pure %[[#FN]] +; CHECK: %[[#FN7]] = OpFunction %[[#VOID]] Const %[[#FN]] +; CHECK: OpFunctionEnd + + +define void @fn8() memory(read) { + ret void +} +; CHECK: %[[#FN8]] = OpFunction %[[#VOID]] Const %[[#FN]] +; CHECK: OpFunctionEnd + + +define void @fn9() alwaysinline readnone { + ret void +} +; CHECK: %[[#FN9]] = OpFunction %[[#VOID]] Inline|Pure %[[#FN]] ; CHECK: OpFunctionEnd