Skip to content

Commit 0f68438

Browse files
adding DXIL and SPIRV codegen
1 parent 087c2df commit 0f68438

File tree

7 files changed

+115
-16
lines changed

7 files changed

+115
-16
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,31 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
9999
I->addAnnotationMetadata("auto-init");
100100
}
101101

102+
static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) {
103+
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
104+
auto *CMP = CGF->Builder.CreateFCmpOLT(
105+
Op0, ConstantFP::get(CGF->Builder.getFloatTy(), 0.0));
106+
107+
if (CGF->CGM.getTarget().getTriple().isDXIL())
108+
return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip,
109+
{CMP}, nullptr);
110+
111+
BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn);
112+
BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn);
113+
114+
CGF->Builder.CreateCondBr(CMP, LT0, End);
115+
116+
CGF->Builder.SetInsertPoint(LT0);
117+
118+
auto *IntrCall = CGF->Builder.CreateIntrinsic(
119+
CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, nullptr);
120+
121+
CGF->Builder.CreateBr(End);
122+
123+
CGF->Builder.SetInsertPoint(End);
124+
return IntrCall;
125+
}
126+
102127
static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
103128
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
104129
const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
@@ -19184,12 +19209,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1918419209

1918519210
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
1918619211
"clip operands types mismatch");
19187-
19188-
Value *Op0 = EmitScalarExpr(E->getArg(0));
19189-
auto *CMP =
19190-
Builder.CreateFCmpOLT(Op0, ConstantFP::get(Builder.getFloatTy(), 0.0));
19191-
return Builder.CreateIntrinsic(
19192-
VoidTy, CGM.getHLSLRuntime().getClipIntrinsic(), {CMP}, nullptr);
19212+
return handleHlslClip(E, this);
1919319213
}
1919419214
return nullptr;
1919519215
}
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s
2-
3-
RWBuffer<float4> Buf;
2+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s
43

54
//CHECK-LABEL: define void @main()
6-
float4 main( ) {
7-
float4 p1 = Buf[0];
5+
void test(float Buf) {
86
//CHECK: [[LOAD:%.*]] = load <4 x float>, ptr %p1{{.*}}, align 16
97
//CHECK-NEXT: [[EXTR:%.*]] = extractelement <4 x float> [[LOAD]], i32 3
108
//CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[EXTR]], 0.000000e+00
119
//CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]])
12-
clip(p1.a);
13-
return p1;
10+
clip(Buf);
1411
}

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,15 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
770770
let stages = [Stages<DXIL1_0, [all_stages]>];
771771
}
772772

773+
def Discard : DXILOp<82, discard> {
774+
let Doc = "discard the current pixel";
775+
let LLVMIntrinsic = int_dx_clip;
776+
let arguments = [Int1Ty];
777+
let result = VoidTy;
778+
let stages = [Stages<DXIL1_0, [pixel]>];
779+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
780+
}
781+
773782
def ThreadId : DXILOp<93, threadId> {
774783
let Doc = "Reads the thread ID";
775784
let LLVMIntrinsic = int_dx_thread_id;
@@ -862,6 +871,15 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
862871
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
863872
}
864873

874+
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
875+
let Doc = "returns the index of the current lane in the wave";
876+
let LLVMIntrinsic = int_dx_wave_getlaneindex;
877+
let arguments = [];
878+
let result = Int32Ty;
879+
let stages = [Stages<DXIL1_0, [all_stages]>];
880+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
881+
}
882+
865883
def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
866884
let Doc = "returns the value from the specified lane";
867885
let LLVMIntrinsic = int_dx_wave_readlane;
@@ -872,10 +890,24 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
872890
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
873891
}
874892

875-
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
876-
let Doc = "returns the index of the current lane in the wave";
877-
let LLVMIntrinsic = int_dx_wave_getlaneindex;
878-
let arguments = [];
893+
def AnnotateHandle : DXILOp<217, annotateHandle> {
894+
let Doc = "annotate handle with resource properties";
895+
let arguments = [HandleTy, ResPropsTy];
896+
let result = HandleTy;
897+
let stages = [Stages<DXIL1_6, [all_stages]>];
898+
}
899+
900+
def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
901+
let Doc = "create resource handle from binding";
902+
let arguments = [ResBindTy, Int32Ty, Int1Ty];
903+
let result = HandleTy;
904+
let stages = [Stages<DXIL1_6, [all_stages]>];
905+
}
906+
907+
def WaveAllBitCount : DXILOp<135, waveAllOp> {
908+
let Doc = "returns the count of bits set to 1 across the wave";
909+
let LLVMIntrinsic = int_dx_wave_active_countbits;
910+
let arguments = [Int1Ty];
879911
let result = Int32Ty;
880912
let stages = [Stages<DXIL1_0, [all_stages]>];
881913
let attributes = [Attributes<DXIL1_0, [ReadNone]>];

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ let isReturn = 1, hasDelaySlot = 0, isBarrier = 0, isTerminator = 1, isNotDuplic
639639
}
640640
def OpLifetimeStart: Op<256, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStart $ptr, $sz">;
641641
def OpLifetimeStop: Op<257, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStop $ptr, $sz">;
642+
def OpDemoteToHelperInvocation: SimpleOp<"OpDemoteToHelperInvocation", 5380>;
642643

643644
// 3.42.18 Atomic Instructions
644645

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
164164
unsigned comparisonOpcode, MachineInstr &I) const;
165165
bool selectCross(Register ResVReg, const SPIRVType *ResType,
166166
MachineInstr &I) const;
167+
bool selectClip(Register ResVReg, const SPIRVType *ResType,
168+
MachineInstr &I) const;
169+
167170
bool selectICmp(Register ResVReg, const SPIRVType *ResType,
168171
MachineInstr &I) const;
169172
bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
@@ -2154,6 +2157,20 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
21542157
return MIB.constrainAllUses(TII, TRI, RBI);
21552158
}
21562159

2160+
bool SPIRVInstructionSelector::selectClip(Register ResVReg,
2161+
const SPIRVType *ResType,
2162+
MachineInstr &I) const {
2163+
2164+
const auto Opcode =
2165+
STI.getTargetTriple().getVulkanVersion() < llvm::VersionTuple(1, 3)
2166+
? SPIRV::OpKill
2167+
: SPIRV::OpDemoteToHelperInvocation;
2168+
2169+
MachineBasicBlock &BB = *I.getParent();
2170+
return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
2171+
.constrainAllUses(TII, TRI, RBI);
2172+
}
2173+
21572174
bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
21582175
const SPIRVType *ResType,
21592176
unsigned CmpOpc,
@@ -2809,6 +2826,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
28092826
selectHandleFromBinding(ResVReg, ResType, I);
28102827
return true;
28112828
}
2829+
case Intrinsic::spv_clip: {
2830+
return selectClip(ResVReg, ResType, I);
2831+
}
28122832
default: {
28132833
std::string DiagMsg;
28142834
raw_string_ostream OS(DiagMsg);

llvm/test/CodeGen/DirectX/clip.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s
2+
3+
; CHECK-LABEL: define void @test_dxil_lowering
4+
; CHECK: call void @dx.op.discard(i32 82, i1 %0)
5+
;
6+
define void @test_dxil_lowering(float noundef %p) #0 {
7+
entry:
8+
%0 = fcmp olt float %p, 0.000000e+00
9+
call void @llvm.dx.clip(i1 %0)
10+
ret void
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
5+
; CHECK-LABEL: define void @test_dxil_lowering
6+
; CHECK: call void @dx.op.discard(i32 82, i1 %0)
7+
;
8+
define spir_func void @test_dxil_lowering(float noundef %Buf) #0 {
9+
entry:
10+
%Buf.addr = alloca float, align 4
11+
store float %Buf, ptr %Buf.addr, align 4
12+
%1 = load float, ptr %Buf.addr, align 4
13+
%2 = fcmp olt float %1, 0.000000e+00
14+
call void @llvm.spv.clip(i1 %2)
15+
ret void
16+
}
17+
18+
declare void @llvm.spv.clip(i1) #1

0 commit comments

Comments
 (0)