Skip to content

Commit 9d300da

Browse files
committed
[DXIL] Using a dx intrinsic for directx backend
1 parent e8a47ba commit 9d300da

File tree

6 files changed

+59
-13
lines changed

6 files changed

+59
-13
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
222222
ResultType = llvm::FixedVectorType::get(CGF.DoubleTy, N);
223223
}
224224

225+
if (CGF.CGM.getTarget().getTriple().isDXIL())
226+
return CGF.Builder.CreateIntrinsic(
227+
/*ReturnType=*/ResultType, Intrinsic::dx_asdouble,
228+
ArrayRef<Value *>{OpLowBits, OpHighBits}, nullptr, "hlsl.asdouble");
229+
225230
if (!E->getArg(0)->getType()->isVectorType()) {
226231
OpLowBits = CGF.Builder.CreateVectorSplat(1, OpLowBits);
227232
OpHighBits = CGF.Builder.CreateVectorSplat(1, OpHighBits);
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
// RUN: %clang_cc1 -finclude-default-header -triple \
22
// RUN: dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o - | \
3-
// RUN: FileCheck %s
3+
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
44
// RUN: %clang_cc1 -finclude-default-header -triple \
55
// RUN: spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
6-
// RUN: FileCheck %s
6+
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-SPV
77

88
// Test lowering of asdouble expansion to shuffle/bitcast and splat when required
99

1010
// CHECK-LABEL: test_uint
1111
double test_uint(uint low, uint high) {
12-
// CHECK: %[[LOW_INSERT:.*]] = insertelement <1 x i32>
13-
// CHECK: %[[LOW_SHUFFLE:.*]] = shufflevector <1 x i32> %[[LOW_INSERT]], {{.*}} zeroinitializer
14-
// CHECK: %[[HIGH_INSERT:.*]] = insertelement <1 x i32>
15-
// CHECK: %[[HIGH_SHUFFLE:.*]] = shufflevector <1 x i32> %[[HIGH_INSERT]], {{.*}} zeroinitializer
16-
17-
// CHECK: %[[SHUFFLE0:.*]] = shufflevector <1 x i32> %[[LOW_SHUFFLE]], <1 x i32> %[[HIGH_SHUFFLE]],
18-
// CHECK-SAME: {{.*}} <i32 0, i32 1>
19-
// CHECK: bitcast <2 x i32> %[[SHUFFLE0]] to double
12+
// CHECK-SPV: %[[LOW_INSERT:.*]] = insertelement <1 x i32>
13+
// CHECK-SPV: %[[LOW_SHUFFLE:.*]] = shufflevector <1 x i32> %[[LOW_INSERT]], {{.*}} zeroinitializer
14+
// CHECK-SPV: %[[HIGH_INSERT:.*]] = insertelement <1 x i32>
15+
// CHECK-SPV: %[[HIGH_SHUFFLE:.*]] = shufflevector <1 x i32> %[[HIGH_INSERT]], {{.*}} zeroinitializer
16+
17+
// CHECK-SPV: %[[SHUFFLE0:.*]] = shufflevector <1 x i32> %[[LOW_SHUFFLE]], <1 x i32> %[[HIGH_SHUFFLE]],
18+
// CHECK-SPV-SAME: {{.*}} <i32 0, i32 1>
19+
// CHECK-SPV: bitcast <2 x i32> %[[SHUFFLE0]] to double
20+
21+
// CHECK-DXIL: call double @llvm.dx.asdouble.i32
2022
return asdouble(low, high);
2123
}
2224

25+
// CHECK-DXIL: declare double @llvm.dx.asdouble.i32
26+
2327
// CHECK-LABEL: test_vuint
2428
double3 test_vuint(uint3 low, uint3 high) {
25-
// CHECK: %[[SHUFFLE1:.*]] = shufflevector
26-
// CHECK-SAME: {{.*}} <i32 0, i32 3, i32 1, i32 4, i32 2, i32 5>
27-
// CHECK: bitcast <6 x i32> %[[SHUFFLE1]] to <3 x double>
29+
// CHECK-SPV: %[[SHUFFLE1:.*]] = shufflevector
30+
// CHECK-SPV-SAME: {{.*}} <i32 0, i32 3, i32 1, i32 4, i32 2, i32 5>
31+
// CHECK-SPV: bitcast <6 x i32> %[[SHUFFLE1]] to <3 x double>
32+
33+
// CHECK-DXIL: call <3 x double> @llvm.dx.asdouble.v3i32
2834
return asdouble(low, high);
2935
}
36+
37+
// CHECK-DXIL: declare <3 x double> @llvm.dx.asdouble.v3i32

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
4646

4747
def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
4848
def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
49+
def int_dx_asdouble : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_double_ty>], [llvm_anyint_ty, LLVMMatchType<0>], [IntrNoMem]>;
4950
def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
5051
def int_dx_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
5152
def int_dx_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,15 @@ def FlattenedThreadIdInGroup : DXILOp<96, flattenedThreadIdInGroup> {
818818
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
819819
}
820820

821+
def MakeDouble : DXILOp<101, makeDouble> {
822+
let Doc = "creates a double value";
823+
let LLVMIntrinsic = int_dx_asdouble;
824+
let arguments = [Int32Ty, Int32Ty];
825+
let result = DoubleTy;
826+
let stages = [Stages<DXIL1_0, [all_stages]>];
827+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
828+
}
829+
821830
def SplitDouble : DXILOp<102, splitDouble> {
822831
let Doc = "Splits a double into 2 uints";
823832
let arguments = [OverloadTy];

llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bool DirectXTTIImpl::isTargetIntrinsicTriviallyScalarizable(
3939
case Intrinsic::dx_frac:
4040
case Intrinsic::dx_rsqrt:
4141
case Intrinsic::dx_wave_readlane:
42+
case Intrinsic::dx_asdouble:
4243
case Intrinsic::dx_splitdouble:
4344
case Intrinsic::dx_firstbituhigh:
4445
case Intrinsic::dx_firstbitshigh:

llvm/test/CodeGen/DirectX/asdouble.ll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
2+
3+
; Test that for scalar and vector inputs, asdouble maps down to the makeDouble
4+
; DirectX op
5+
6+
define noundef double @asdouble_scalar(i32 noundef %low, i32 noundef %high) {
7+
; CHECK: call double @dx.op.makeDouble(i32 101, i32 %low, i32 %high)
8+
%ret = call double @llvm.dx.asdouble.i32(i32 %low, i32 %high)
9+
ret double %ret
10+
}
11+
12+
declare double @llvm.dx.asdouble.i32(i32, i32)
13+
14+
define noundef <3 x double> @asdouble_vec(<3 x i32> noundef %low, <3 x i32> noundef %high) {
15+
; CHECK: call double @dx.op.makeDouble(i32 101, i32 %low.i0, i32 %high.i0)
16+
; CHECK: call double @dx.op.makeDouble(i32 101, i32 %low.i1, i32 %high.i1)
17+
; CHECK: call double @dx.op.makeDouble(i32 101, i32 %low.i2, i32 %high.i2)
18+
%ret = call <3 x double> @llvm.dx.asdouble.v3i32(<3 x i32> %low, <3 x i32> %high)
19+
ret <3 x double> %ret
20+
}
21+
22+
declare <3 x double> @llvm.dx.asdouble.v3i32(<3 x i32>, <3 x i32>)

0 commit comments

Comments
 (0)