Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,16 @@ void SPIRVPassConfig::addIRPasses() {

TargetPassConfig::addIRPasses();

addPass(createSPIRVRegularizerPass());
addPass(createSPIRVPrepareFunctionsPass(TM));
addPass(createSPIRVPrepareGlobalsPass());

// Variadic function calls aren't supported in shader code.
// This needs to come before SPIRVPrepareFunctions because this
// may introduce intrinsic calls.
if (!TM.getSubtargetImpl()->isShader()) {
addPass(createExpandVariadicsPass(ExpandVariadicsMode::Lowering));
}

addPass(createSPIRVRegularizerPass());
addPass(createSPIRVPrepareFunctionsPass(TM));
addPass(createSPIRVPrepareGlobalsPass());
}

void SPIRVPassConfig::addISelPrepare() {
Expand Down
34 changes: 20 additions & 14 deletions llvm/lib/Transforms/IPO/ExpandVariadics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#include "llvm/Transforms/IPO/ExpandVariadics.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
Expand Down Expand Up @@ -124,13 +125,16 @@ class VariadicABIInfo {
};
virtual VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) = 0;

// Per-target overrides of special symbols.
virtual bool ignoreFunction(Function *F) { return false; }

// Targets implemented so far all have the same trivial lowering for these
bool vaEndIsNop() { return true; }
bool vaCopyIsMemcpy() { return true; }

// Any additional address spaces used in va intrinsics that should be
// expanded.
virtual SmallVector<unsigned> getTargetSpecificVaIntrinAddrSpaces() const {
return {};
}

virtual ~VariadicABIInfo() = default;
};

Expand Down Expand Up @@ -238,9 +242,6 @@ class ExpandVariadics : public ModulePass {
F->hasFnAttribute(Attribute::Naked))
return false;

if (ABI->ignoreFunction(F))
return false;

if (!isValidCallingConv(F))
return false;

Expand Down Expand Up @@ -364,13 +365,21 @@ bool ExpandVariadics::runOnModule(Module &M) {
// variadic functions have also been replaced.

{
// 0 and AllocaAddrSpace are sufficient for the targets implemented so far
unsigned Addrspace = 0;
Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace);

Addrspace = DL.getAllocaAddrSpace();
if (Addrspace != 0)
Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace);

// Process any addrspaces targets declare to be important.
const SmallVector<unsigned> &TargetASVec =
ABI->getTargetSpecificVaIntrinAddrSpaces();
for (unsigned TargetAS : TargetASVec) {
if (TargetAS == 0 || TargetAS == DL.getAllocaAddrSpace())
continue;
Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, TargetAS);
}
}

if (Mode != ExpandVariadicsMode::Lowering)
Expand Down Expand Up @@ -618,9 +627,6 @@ bool ExpandVariadics::expandCall(Module &M, IRBuilder<> &Builder, CallBase *CB,
bool Changed = false;
const DataLayout &DL = M.getDataLayout();

if (ABI->ignoreFunction(CB->getCalledFunction()))
return Changed;

if (!expansionApplicableToFunctionCall(CB)) {
if (rewriteABI())
report_fatal_error("Cannot lower callbase instruction");
Expand Down Expand Up @@ -978,10 +984,9 @@ struct SPIRV final : public VariadicABIInfo {
return {A, false};
}

// The SPIR-V backend has special handling for SPIR-V mangled printf
// functions.
bool ignoreFunction(Function *F) override {
return F->getName().starts_with('_') && F->getName().contains("printf");
// We will likely see va intrinsics in the generic addrspace (4).
SmallVector<unsigned> getTargetSpecificVaIntrinAddrSpaces() const override {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason this handling existed was to preserve the 'old' printf handling. It seems a little strange to only lower functions based off of the address space, this is supposed to be the canonical variadic ABI for the target. Ideally we wouldn't leave anything unlowered. I mostly hacked around the printf issue because I don't know anything about its intended use.

Here's a fun hack if you just want the OpenMP printf to work, just rename it with asm("foobar").

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The address space handing was there previously and you didn't modify it in your change. The existing code has some weird logic about address spaces, only lowering 0 and the alloca AS. I have no idea why that is, but I think it's safer to add a known-good case than start processing everything for all targets.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhuber6 Did you have any more feedback on this PR? I think there was a bit of a misunderstanding before, the proposed changes to ExpandVariadics should not be specific to printf (in the latest iteration of the PR), this PR actually aims to remove all of that, and I think the addition of handling target address spaces fits reasonably within the existing code that already has a list of address spaces to try to lower. Thanks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhuber6 Mind taking another look at this with the above context? If you don't feel comfortable reviewing I can try to find someone else, thanks

return {4};
}
};

Expand Down Expand Up @@ -1041,6 +1046,7 @@ std::unique_ptr<VariadicABIInfo> VariadicABIInfo::create(const Triple &T) {
}

case Triple::spirv:
case Triple::spirv32:
case Triple::spirv64: {
return std::make_unique<SPIRV>();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers < %s 2>&1 | FileCheck %s

; CHECK: OpName [[MAIN:%.*]] "main"
; CHECK: [[MAIN]] = OpFunction
; CHECK-NOT: OPFunctionEnd
; CHECK: OpLifetimeStart
; CHECK-NOT: OPFunctionEnd
; CHECK: OpLifetimeStop
; CHECK: OpFunctionEnd

@.str = private unnamed_addr addrspace(1) constant [3 x i8] c"%s\00", align 1
@.str.1 = private unnamed_addr addrspace(1) constant [4 x i8] c"hey\00", align 1

declare spir_func noundef i32 @_Z7vprintfPKcz(ptr addrspace(4) noundef %0, ...) addrspace(9)

define spir_func noundef i32 @_ZN4ompx6printfEPKcz(ptr addrspace(4) noundef %Format, ...) addrspace(9) {
entry:
%retval = alloca i32, align 4
%Format.addr = alloca ptr addrspace(4), align 8
%vlist = alloca ptr addrspace(4), align 8
%retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
%Format.addr.ascast = addrspacecast ptr %Format.addr to ptr addrspace(4)
%vlist.ascast = addrspacecast ptr %vlist to ptr addrspace(4)
store ptr addrspace(4) %Format, ptr addrspace(4) %Format.addr.ascast, align 8
call addrspace(9) void @llvm.va_start.p4(ptr addrspace(4) %vlist.ascast)
%0 = load ptr addrspace(4), ptr addrspace(4) %Format.addr.ascast, align 8
%1 = load ptr addrspace(4), ptr addrspace(4) %vlist.ascast, align 8
%call = call spir_func noundef addrspace(9) i32 (ptr addrspace(4), ...) @_Z7vprintfPKcz(ptr addrspace(4) noundef %0, ptr addrspace(4) noundef %1)
ret i32 %call
}

declare void @llvm.va_start.p4(ptr addrspace(4)) addrspace(9)

define noundef i32 @main() addrspace(9) {
entry:
%retval = alloca i32, align 4
%retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
store i32 0, ptr addrspace(4) %retval.ascast, align 4
%call = call spir_func noundef addrspace(9) i32 (ptr addrspace(4), ...) @_ZN4ompx6printfEPKcz(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @.str to ptr addrspace(4)), ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @.str.1 to ptr addrspace(4))) #5
ret i32 0
}
6 changes: 4 additions & 2 deletions llvm/test/CodeGen/SPIRV/llc-pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
; SPIRV-O0-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; SPIRV-O0-NEXT: Scalarize Masked Memory Intrinsics
; SPIRV-O0-NEXT: Expand reduction intrinsics
; SPIRV-O0-NEXT: Expand variadic functions
; SPIRV-O0-NEXT: FunctionPass Manager
; SPIRV-O0-NEXT: SPIR-V Regularizer
; SPIRV-O0-NEXT: SPIRV prepare functions
; SPIRV-O0-NEXT: SPIRV prepare global variables
; SPIRV-O0-NEXT: Expand variadic functions
; SPIRV-O0-NEXT: FunctionPass Manager
; SPIRV-O0-NEXT: Lower invoke and unwind, for unwindless code generators
; SPIRV-O0-NEXT: Remove unreachable blocks from the CFG
Expand Down Expand Up @@ -136,10 +137,11 @@
; SPIRV-Opt-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; SPIRV-Opt-NEXT: Scalarize Masked Memory Intrinsics
; SPIRV-Opt-NEXT: Expand reduction intrinsics
; SPIRV-Opt-NEXT: Expand variadic functions
; SPIRV-Opt-NEXT: FunctionPass Manager
; SPIRV-Opt-NEXT: SPIR-V Regularizer
; SPIRV-Opt-NEXT: SPIRV prepare functions
; SPIRV-Opt-NEXT: SPIRV prepare global variables
; SPIRV-Opt-NEXT: Expand variadic functions
; SPIRV-Opt-NEXT: FunctionPass Manager
; SPIRV-Opt-NEXT: Dominator Tree Construction
; SPIRV-Opt-NEXT: Natural Loop Information
Expand Down
36 changes: 19 additions & 17 deletions llvm/test/CodeGen/SPIRV/printf.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,35 @@

; CHECK: %[[#ExtImport:]] = OpExtInstImport "OpenCL.std"
; CHECK: %[[#Char:]] = OpTypeInt 8 0
; CHECK: %[[#CharPtr:]] = OpTypePointer UniformConstant %[[#Char]]
; CHECK: %[[#ConstCharPtr:]] = OpTypePointer UniformConstant %[[#Char]]
; CHECK: %[[#VarargStruct:]] = OpTypeStruct %[[#Char]]
; CHECK: %[[#VarargStructPtr:]] = OpTypePointer Function %[[#VarargStruct]]
; CHECK: %[[#CharPtr:]] = OpTypePointer Function %[[#Char]]
; CHECK: %[[#IntConst:]] = OpConstant %[[#Char]] 97
; CHECK: %[[#GV:]] = OpVariable %[[#]] UniformConstant %[[#]]
; CHECK: OpFunction
; CHECK: %[[#Arg1:]] = OpFunctionParameter
; CHECK: %[[#Arg2:]] = OpFunctionParameter
; CHECK: %[[#CastedGV:]] = OpBitcast %[[#CharPtr]] %[[#GV]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#CastedGV]] %[[#ArgConst:]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#CastedGV]] %[[#ArgConst]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#Arg1]] %[[#ArgConst:]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#Arg1]] %[[#ArgConst]]
; CHECK-NEXT: %[[#CastedArg2:]] = OpBitcast %[[#CharPtr]] %[[#Arg2]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#CastedArg2]] %[[#ArgConst]]
; CHECK-NEXT: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#CastedArg2]] %[[#ArgConst]]
; CHECK: %[[#Arg:]] = OpFunctionParameter
; CHECK: %[[#VarargBuffer1:]] = OpVariable %[[#VarargStructPtr]] Function
; CHECK: %[[#VarargBuffer2:]] = OpVariable %[[#VarargStructPtr]] Function
; CHECK: %[[#CastedBuffer1:]] = OpBitcast %[[#CharPtr]] %[[#VarargBuffer1]]
; CHECK: %[[#GEP1:]] = OpInBoundsPtrAccessChain %[[#CharPtr]] %[[#VarargBuffer1]]
; CHECK: OpStore %[[#GEP1]] %[[#IntConst]] Aligned 1
; CHECK: %[[#CastedGV:]] = OpBitcast %[[#ConstCharPtr]] %[[#GV]]
; CHECK: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#CastedGV]] %[[#CastedBuffer1:]]
; CHECK: %[[#CastedBuffer2:]] = OpBitcast %[[#CharPtr]] %[[#VarargBuffer2]]
; CHECK: %[[#GEP2:]] = OpInBoundsPtrAccessChain %[[#CharPtr]] %[[#VarargBuffer2]]
; CHECK: OpStore %[[#GEP2]] %[[#IntConst]] Aligned 1
; CHECK: OpExtInst %[[#]] %[[#ExtImport]] printf %[[#Arg]] %[[#CastedBuffer2:]]
; CHECK: OpFunctionEnd

%struct = type { [6 x i8] }

@FmtStr = internal addrspace(2) constant [6 x i8] c"c=%c\0A\00", align 1

define spir_kernel void @foo(ptr addrspace(2) %_arg_fmt1, ptr addrspace(2) byval(%struct) %_arg_fmt2) {
define spir_kernel void @foo(ptr addrspace(2) %_arg_fmt) {
entry:
%r1 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z6printfPU3AS2Kcz(ptr addrspace(2) @FmtStr, i8 signext 97)
%r2 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z18__spirv_ocl_printfPU3AS2Kcz(ptr addrspace(2) @FmtStr, i8 signext 97)
%r3 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z6printfPU3AS2Kcz(ptr addrspace(2) %_arg_fmt1, i8 signext 97)
%r4 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z18__spirv_ocl_printfPU3AS2Kcz(ptr addrspace(2) %_arg_fmt1, i8 signext 97)
%r5 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z6printfPU3AS2Kcz(ptr addrspace(2) %_arg_fmt2, i8 signext 97)
%r6 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z18__spirv_ocl_printfPU3AS2Kcz(ptr addrspace(2) %_arg_fmt2, i8 signext 97)
%r2 = tail call spir_func i32 (ptr addrspace(2), ...) @_Z18__spirv_ocl_printfPU3AS2Kcz(ptr addrspace(2) %_arg_fmt, i8 signext 97)
ret void
}

Expand Down
Loading