Skip to content

Commit

Permalink
adding DXIL and SPIRV codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
joaosaffran-zz committed Nov 4, 2024
1 parent a92e64d commit 0ce2597
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 35 deletions.
32 changes: 26 additions & 6 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,31 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
I->addAnnotationMetadata("auto-init");
}

static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) {
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
auto *CMP = CGF->Builder.CreateFCmpOLT(
Op0, ConstantFP::get(CGF->Builder.getFloatTy(), 0.0));

if (CGF->CGM.getTarget().getTriple().isDXIL())
return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip,
{CMP}, nullptr);

BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn);
BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn);

CGF->Builder.CreateCondBr(CMP, LT0, End);

CGF->Builder.SetInsertPoint(LT0);

auto *IntrCall = CGF->Builder.CreateIntrinsic(
CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, nullptr);

CGF->Builder.CreateBr(End);

CGF->Builder.SetInsertPoint(End);
return IntrCall;
}

static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
Expand Down Expand Up @@ -19097,12 +19122,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {

assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
"clip operands types mismatch");

Value *Op0 = EmitScalarExpr(E->getArg(0));
auto *CMP =
Builder.CreateFCmpOLT(Op0, ConstantFP::get(Builder.getFloatTy(), 0.0));
return Builder.CreateIntrinsic(
VoidTy, CGM.getHLSLRuntime().getClipIntrinsic(), {CMP}, nullptr);
return handleHlslClip(E, this);
}
return nullptr;
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
GENERATE_HLSL_INTRINSIC_FUNCTION(Clip, clip)
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding)

//===----------------------------------------------------------------------===//
Expand Down
9 changes: 3 additions & 6 deletions clang/test/CodeGenHLSL/builtins/clip.hlsl
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s

RWBuffer<float4> Buf;
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s

//CHECK-LABEL: define void @main()
float4 main( ) {
float4 p1 = Buf[0];
void test(float Buf) {
//CHECK: [[LOAD:%.*]] = load <4 x float>, ptr %p1{{.*}}, align 16
//CHECK-NEXT: [[EXTR:%.*]] = extractelement <4 x float> [[LOAD]], i32 3
//CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[EXTR]], 0.000000e+00
//CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]])
clip(p1.a);
return p1;
clip(Buf);
}
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/IntrinsicsSPIRV.td
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ let TargetPrefix = "spv" in {
def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
def int_spv_radians : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_group_memory_barrier_with_group_sync : DefaultAttrsIntrinsic<[], [], []>;
def int_spv_clip : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrNoMem]>;
def int_spv_clip : Intrinsic<[], [], []>;

// Create resource handle given the binding information. Returns a
// type appropriate for the kind of resource given the set id, binding id,
Expand Down
51 changes: 30 additions & 21 deletions llvm/lib/Target/DirectX/DXIL.td
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,15 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
let stages = [Stages<DXIL1_0, [all_stages]>];
}

def Discard : DXILOp<82, discard> {
let Doc = "discard the current pixel";
let LLVMIntrinsic = int_dx_clip;
let arguments = [Int1Ty];
let result = VoidTy;
let stages = [Stages<DXIL1_0, [pixel]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}

def ThreadId : DXILOp<93, threadId> {
let Doc = "Reads the thread ID";
let LLVMIntrinsic = int_dx_thread_id;
Expand Down Expand Up @@ -788,20 +797,6 @@ def SplitDouble : DXILOp<102, splitDouble> {
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}

def AnnotateHandle : DXILOp<217, annotateHandle> {
let Doc = "annotate handle with resource properties";
let arguments = [HandleTy, ResPropsTy];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
}

def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
let Doc = "create resource handle from binding";
let arguments = [ResBindTy, Int32Ty, Int1Ty];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
}

def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
let Doc = "returns 1 for the first lane in the wave";
let LLVMIntrinsic = int_dx_wave_is_first_lane;
Expand All @@ -811,6 +806,15 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}

def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
let Doc = "returns the index of the current lane in the wave";
let LLVMIntrinsic = int_dx_wave_getlaneindex;
let arguments = [];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}

def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
let Doc = "returns the value from the specified lane";
let LLVMIntrinsic = int_dx_wave_readlane;
Expand All @@ -821,11 +825,16 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}

def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
let Doc = "returns the index of the current lane in the wave";
let LLVMIntrinsic = int_dx_wave_getlaneindex;
let arguments = [];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
def AnnotateHandle : DXILOp<217, annotateHandle> {
let Doc = "annotate handle with resource properties";
let arguments = [HandleTy, ResPropsTy];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
}

def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
let Doc = "create resource handle from binding";
let arguments = [ResBindTy, Int32Ty, Int1Ty];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
}
1 change: 1 addition & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ let isReturn = 1, hasDelaySlot = 0, isBarrier = 0, isTerminator = 1, isNotDuplic
}
def OpLifetimeStart: Op<256, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStart $ptr, $sz">;
def OpLifetimeStop: Op<257, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStop $ptr, $sz">;
def OpDemoteToHelperInvocation: SimpleOp<"OpDemoteToHelperInvocation", 5380>;

// 3.42.18 Atomic Instructions

Expand Down
20 changes: 20 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
unsigned comparisonOpcode, MachineInstr &I) const;
bool selectCross(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
bool selectClip(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;

bool selectICmp(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
Expand Down Expand Up @@ -1966,6 +1969,20 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectClip(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {

const auto Opcode =
STI.getTargetTriple().getVulkanVersion() < llvm::VersionTuple(1, 3)
? SPIRV::OpKill
: SPIRV::OpDemoteToHelperInvocation;

MachineBasicBlock &BB = *I.getParent();
return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
const SPIRVType *ResType,
unsigned CmpOpc,
Expand Down Expand Up @@ -2599,6 +2616,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
selectHandleFromBinding(ResVReg, ResType, I);
return true;
}
case Intrinsic::spv_clip: {
return selectClip(ResVReg, ResType, I);
}
default: {
std::string DiagMsg;
raw_string_ostream OS(DiagMsg);
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/CodeGen/DirectX/clip.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s

; CHECK-LABEL: define void @test_dxil_lowering
; CHECK: call void @dx.op.discard(i32 82, i1 %0)
;
define void @test_dxil_lowering(float noundef %p) #0 {
entry:
%0 = fcmp olt float %p, 0.000000e+00
call void @llvm.dx.clip(i1 %0)
ret void
}
18 changes: 18 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}


; CHECK-LABEL: define void @test_dxil_lowering
; CHECK: call void @dx.op.discard(i32 82, i1 %0)
;
define spir_func void @test_dxil_lowering(float noundef %Buf) #0 {
entry:
%Buf.addr = alloca float, align 4
store float %Buf, ptr %Buf.addr, align 4
%1 = load float, ptr %Buf.addr, align 4
%2 = fcmp olt float %1, 0.000000e+00
call void @llvm.spv.clip(i1 %2)
ret void
}

declare void @llvm.spv.clip(i1) #1

0 comments on commit 0ce2597

Please sign in to comment.