Skip to content

Commit 0ce2597

Browse files
adding DXIL and SPIRV codegen
1 parent a92e64d commit 0ce2597

File tree

9 files changed

+110
-35
lines changed

9 files changed

+110
-35
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));
@@ -19097,12 +19122,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1909719122

1909819123
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
1909919124
"clip operands types mismatch");
19100-
19101-
Value *Op0 = EmitScalarExpr(E->getArg(0));
19102-
auto *CMP =
19103-
Builder.CreateFCmpOLT(Op0, ConstantFP::get(Builder.getFloatTy(), 0.0));
19104-
return Builder.CreateIntrinsic(
19105-
VoidTy, CGM.getHLSLRuntime().getClipIntrinsic(), {CMP}, nullptr);
19125+
return handleHlslClip(E, this);
1910619126
}
1910719127
return nullptr;
1910819128
}

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ class CGHLSLRuntime {
9191
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
9292
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
9393
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
94-
GENERATE_HLSL_INTRINSIC_FUNCTION(Clip, clip)
9594
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding)
9695

9796
//===----------------------------------------------------------------------===//
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/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ let TargetPrefix = "spv" in {
8888
def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
8989
def int_spv_radians : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
9090
def int_spv_group_memory_barrier_with_group_sync : DefaultAttrsIntrinsic<[], [], []>;
91-
def int_spv_clip : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrNoMem]>;
91+
def int_spv_clip : Intrinsic<[], [], []>;
9292

9393
// Create resource handle given the binding information. Returns a
9494
// type appropriate for the kind of resource given the set id, binding id,

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,15 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
739739
let stages = [Stages<DXIL1_0, [all_stages]>];
740740
}
741741

742+
def Discard : DXILOp<82, discard> {
743+
let Doc = "discard the current pixel";
744+
let LLVMIntrinsic = int_dx_clip;
745+
let arguments = [Int1Ty];
746+
let result = VoidTy;
747+
let stages = [Stages<DXIL1_0, [pixel]>];
748+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
749+
}
750+
742751
def ThreadId : DXILOp<93, threadId> {
743752
let Doc = "Reads the thread ID";
744753
let LLVMIntrinsic = int_dx_thread_id;
@@ -788,20 +797,6 @@ def SplitDouble : DXILOp<102, splitDouble> {
788797
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
789798
}
790799

791-
def AnnotateHandle : DXILOp<217, annotateHandle> {
792-
let Doc = "annotate handle with resource properties";
793-
let arguments = [HandleTy, ResPropsTy];
794-
let result = HandleTy;
795-
let stages = [Stages<DXIL1_6, [all_stages]>];
796-
}
797-
798-
def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
799-
let Doc = "create resource handle from binding";
800-
let arguments = [ResBindTy, Int32Ty, Int1Ty];
801-
let result = HandleTy;
802-
let stages = [Stages<DXIL1_6, [all_stages]>];
803-
}
804-
805800
def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
806801
let Doc = "returns 1 for the first lane in the wave";
807802
let LLVMIntrinsic = int_dx_wave_is_first_lane;
@@ -811,6 +806,15 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
811806
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
812807
}
813808

809+
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
810+
let Doc = "returns the index of the current lane in the wave";
811+
let LLVMIntrinsic = int_dx_wave_getlaneindex;
812+
let arguments = [];
813+
let result = Int32Ty;
814+
let stages = [Stages<DXIL1_0, [all_stages]>];
815+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
816+
}
817+
814818
def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
815819
let Doc = "returns the value from the specified lane";
816820
let LLVMIntrinsic = int_dx_wave_readlane;
@@ -821,11 +825,16 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
821825
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
822826
}
823827

824-
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
825-
let Doc = "returns the index of the current lane in the wave";
826-
let LLVMIntrinsic = int_dx_wave_getlaneindex;
827-
let arguments = [];
828-
let result = Int32Ty;
829-
let stages = [Stages<DXIL1_0, [all_stages]>];
830-
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
828+
def AnnotateHandle : DXILOp<217, annotateHandle> {
829+
let Doc = "annotate handle with resource properties";
830+
let arguments = [HandleTy, ResPropsTy];
831+
let result = HandleTy;
832+
let stages = [Stages<DXIL1_6, [all_stages]>];
833+
}
834+
835+
def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
836+
let Doc = "create resource handle from binding";
837+
let arguments = [ResBindTy, Int32Ty, Int1Ty];
838+
let result = HandleTy;
839+
let stages = [Stages<DXIL1_6, [all_stages]>];
831840
}

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

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

640641
// 3.42.18 Atomic Instructions
641642

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
147147
unsigned comparisonOpcode, MachineInstr &I) const;
148148
bool selectCross(Register ResVReg, const SPIRVType *ResType,
149149
MachineInstr &I) const;
150+
bool selectClip(Register ResVReg, const SPIRVType *ResType,
151+
MachineInstr &I) const;
152+
150153
bool selectICmp(Register ResVReg, const SPIRVType *ResType,
151154
MachineInstr &I) const;
152155
bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
@@ -1966,6 +1969,20 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
19661969
return MIB.constrainAllUses(TII, TRI, RBI);
19671970
}
19681971

1972+
bool SPIRVInstructionSelector::selectClip(Register ResVReg,
1973+
const SPIRVType *ResType,
1974+
MachineInstr &I) const {
1975+
1976+
const auto Opcode =
1977+
STI.getTargetTriple().getVulkanVersion() < llvm::VersionTuple(1, 3)
1978+
? SPIRV::OpKill
1979+
: SPIRV::OpDemoteToHelperInvocation;
1980+
1981+
MachineBasicBlock &BB = *I.getParent();
1982+
return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
1983+
.constrainAllUses(TII, TRI, RBI);
1984+
}
1985+
19691986
bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
19701987
const SPIRVType *ResType,
19711988
unsigned CmpOpc,
@@ -2599,6 +2616,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
25992616
selectHandleFromBinding(ResVReg, ResType, I);
26002617
return true;
26012618
}
2619+
case Intrinsic::spv_clip: {
2620+
return selectClip(ResVReg, ResType, I);
2621+
}
26022622
default: {
26032623
std::string DiagMsg;
26042624
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)