diff --git a/llvm/include/llvm/IR/CMakeLists.txt b/llvm/include/llvm/IR/CMakeLists.txt --- a/llvm/include/llvm/IR/CMakeLists.txt +++ b/llvm/include/llvm/IR/CMakeLists.txt @@ -8,6 +8,7 @@ tablegen(LLVM IntrinsicsAMDGPU.h -gen-intrinsic-enums -intrinsic-prefix=amdgcn) tablegen(LLVM IntrinsicsARM.h -gen-intrinsic-enums -intrinsic-prefix=arm) tablegen(LLVM IntrinsicsBPF.h -gen-intrinsic-enums -intrinsic-prefix=bpf) +tablegen(LLVM IntrinsicsDirectX.h -gen-intrinsic-enums -intrinsic-prefix=dxil) tablegen(LLVM IntrinsicsHexagon.h -gen-intrinsic-enums -intrinsic-prefix=hexagon) tablegen(LLVM IntrinsicsMips.h -gen-intrinsic-enums -intrinsic-prefix=mips) tablegen(LLVM IntrinsicsNVPTX.h -gen-intrinsic-enums -intrinsic-prefix=nvvm) diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -2044,3 +2044,4 @@ include "llvm/IR/IntrinsicsRISCV.td" include "llvm/IR/IntrinsicsSPIRV.td" include "llvm/IR/IntrinsicsVE.td" +include "llvm/IR/IntrinsicsDirectX.td" diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -0,0 +1,20 @@ +//===- IntrinsicsDirectX.td - Defines DirectX intrinsics ---*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the DirectX-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "dxil" in { + +def int_dxil_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; +def int_dxil_group_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; +def int_dxil_thread_id_in_group : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; +def int_dxil_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrWillReturn]>; + +} diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -36,6 +36,7 @@ #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/IntrinsicsBPF.h" +#include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/IntrinsicsHexagon.h" #include "llvm/IR/IntrinsicsMips.h" #include "llvm/IR/IntrinsicsNVPTX.h" diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -22,10 +22,14 @@ def Unary : dxil_class<"Unary">; def Binary : dxil_class<"Binary">; +def FlattenedThreadIdInGroupClass : dxil_class<"FlattenedThreadIdInGroup">; +def ThreadIdInGroupClass : dxil_class<"ThreadIdInGroup">; +def ThreadIdClass : dxil_class<"ThreadId">; +def GroupIdClass : dxil_class<"GroupId">; def binary_uint : dxil_category<"Binary uint">; def unary_float : dxil_category<"Unary float">; - +def ComputeID : dxil_category<"Compute/Mesh/Amplification shader">; // The parameter description for a DXIL instruction @@ -105,3 +109,36 @@ ], ["uints"]>, dxil_map_intrinsic; + +def ThreadId :dxil_op< "ThreadId", 93, ThreadIdClass, ComputeID, "reads the thread ID", "i32;", "rn", + [ + dxil_param<0, "i32", "", "thread ID component">, + dxil_param<1, "i32", "opcode", "DXIL opcode">, + dxil_param<2, "i32", "component", "component to read (x,y,z)"> + ]>, + dxil_map_intrinsic; + +def GroupId :dxil_op< "GroupId", 94, GroupIdClass, ComputeID, "reads the group ID (SV_GroupID)", "i32;", "rn", + [ + dxil_param<0, "i32", "", "group ID component">, + dxil_param<1, "i32", "opcode", "DXIL opcode">, + dxil_param<2, "i32", "component", "component to read"> + ]>, + dxil_map_intrinsic; + +def ThreadIdInGroup :dxil_op< "ThreadIdInGroup", 95, ThreadIdInGroupClass, ComputeID, + "reads the thread ID within the group (SV_GroupThreadID)", "i32;", "rn", + [ + dxil_param<0, "i32", "", "thread ID in group component">, + dxil_param<1, "i32", "opcode", "DXIL opcode">, + dxil_param<2, "i32", "component", "component to read (x,y,z)"> + ]>, + dxil_map_intrinsic; + +def FlattenedThreadIdInGroup :dxil_op< "FlattenedThreadIdInGroup", 96, FlattenedThreadIdInGroupClass, ComputeID, + "provides a flattened index for a given thread within a given group (SV_GroupIndex)", "i32;", "rn", + [ + dxil_param<0, "i32", "", "result">, + dxil_param<1, "i32", "opcode", "DXIL opcode"> + ]>, + dxil_map_intrinsic; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" diff --git a/llvm/test/CodeGen/DirectX/comput_ids.ll b/llvm/test/CodeGen/DirectX/comput_ids.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/comput_ids.ll @@ -0,0 +1,51 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for all ComputeID dxil operations are generated. + +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK-LABEL:test_thread_id +; Function Attrs: noinline nounwind optnone +define i32 @test_thread_id(i32 %a) #0 { +entry: +; CHECK:call i32 @dx.op.threadId.i32(i32 93, i32 %{{.*}}) + %0 = call i32 @llvm.dxil.thread.id(i32 %a) + ret i32 %0 +} + +; CHECK-LABEL:test_group_id +; Function Attrs: noinline nounwind optnone +define i32 @test_group_id(i32 %a) #0 { +entry: +; CHECK:call i32 @dx.op.groupId.i32(i32 94, i32 %{{.*}}) + %0 = call i32 @llvm.dxil.group.id(i32 %a) + ret i32 %0 +} + +; CHECK-LABEL:test_thread_id_in_group +; Function Attrs: noinline nounwind optnone +define i32 @test_thread_id_in_group(i32 %a) #0 { +entry: +; CHECK:call i32 @dx.op.threadIdInGroup.i32(i32 95, i32 %{{.*}}) + %0 = call i32 @llvm.dxil.thread.id.in.group(i32 %a) + ret i32 %0 +} + +; CHECK-LABEL:test_flattened_thread_id_in_group +; Function Attrs: noinline nounwind optnone +define i32 @test_flattened_thread_id_in_group() #0 { +entry: +; CHECK:call i32 @dx.op.flattenedThreadIdInGroup.i32(i32 96) + %0 = call i32 @llvm.dxil.flattened.thread.id.in.group() + ret i32 %0 +} + +; Function Attrs: nounwind readnone willreturn +declare i32 @llvm.dxil.thread.id(i32) #1 +declare i32 @llvm.dxil.group.id(i32) #1 +declare i32 @llvm.dxil.flattened.thread.id.in.group() #1 +declare i32 @llvm.dxil.thread.id.in.group(i32) #1 + +attributes #0 = { noinline nounwind } +attributes #1 = { nounwind readnone willreturn }