Skip to content

Commit 00cd823

Browse files
authored
[DxilOp] Allow generation of illegal DXIL operations. (microsoft#6543)
This change removes the IsOverloadLegal check in OP::GetOpFunc. It will permit the generation of illegal DXIL operations. Subsequently, the validation should catch these illegal DXIL operations if they are not optimized later in SimplifyDxilCall. Fixes microsoft#6410
1 parent 643523a commit 00cd823

File tree

4 files changed

+149
-1
lines changed

4 files changed

+149
-1
lines changed

lib/DXIL/DxilOperations.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3564,8 +3564,14 @@ void OP::UpdateCache(OpCodeClass opClass, Type *Ty, llvm::Function *F) {
35643564
Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
35653565
if (opCode == OpCode::NumOpCodes)
35663566
return nullptr;
3567-
if (!IsOverloadLegal(opCode, pOverloadType))
3567+
if (!pOverloadType)
35683568
return nullptr;
3569+
// Illegal overloads are generated and eliminated by DXIL op constant
3570+
// evaluation for a number of cases where a double overload of an HL intrinsic
3571+
// that otherwise does not support double is used for literal values, when
3572+
// there is no constant evaluation for the intrinsic in CodeGen.
3573+
// Illegal overloads of DXIL intrinsics may survive through to final DXIL,
3574+
// but these will be caught by the validator, and this is not a regression.
35693575

35703576
OpCodeClass opClass = m_OpCodeProps[(unsigned)opCode].opCodeClass;
35713577
Function *&F =
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %dxc -T vs_6_0 %s -E main | FileCheck %s
2+
// RUN: not %dxc -T vs_6_0 %s -E main -DNO_FOLD 2>&1 | FileCheck %s --check-prefixes=NO_FOLD
3+
4+
// The code path generates invalid overload. The invalid overload will either be
5+
// constant folded away, or caught by the validator.
6+
7+
// Ensure fmod is constant evaluated during codegen, or dxil const eval
8+
// TODO: handle fp specials properly, tracked with https://github.com/microsoft/DirectXShaderCompiler/issues/6567
9+
10+
11+
RWBuffer<float4> results : register(u0);
12+
13+
[shader("vertex")]
14+
void main(bool b : B) {
15+
uint i = 0;
16+
17+
// Literal float
18+
// 2.5, -2.5, 2.5, -2.5
19+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 0, i32 undef, float 2.500000e+00, float -2.500000e+00, float 2.500000e+00, float -2.500000e+00, i8 15)
20+
results[i++] = float4(fmod(5.5, 3.0),
21+
fmod(-5.5, 3.0),
22+
fmod(5.5, -3.0),
23+
fmod(-5.5, -3.0));
24+
25+
// Explicit float
26+
// 2.5, -2.5, 2.5, -2.5
27+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 1, i32 undef, float 2.500000e+00, float -2.500000e+00, float 2.500000e+00, float -2.500000e+00, i8 15)
28+
results[i++] = float4(fmod(5.5f, 3.0f),
29+
fmod(-5.5f, 3.0f),
30+
fmod(5.5f, -3.0f),
31+
fmod(-5.5f, -3.0f));
32+
33+
#ifdef SPECIALS
34+
// Literal float
35+
// 0.0, -0.0, NaN, -NaN
36+
// SPECIALS: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 2, i32 undef, float 0.000000e+00, -0.000000e+00, float 0x7FF8000000000000, float 0x7FF8000000000000, i8 15)
37+
results[i++] = float4(fmod(0.0, 1.0),
38+
fmod(-0.0, 1.0),
39+
fmod(5.5, 0.0),
40+
fmod(-5.5, 0.0));
41+
42+
// Explicit float
43+
// 0.0, -0.0, NaN, -NaN
44+
// SPECIALS: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 3, i32 undef, float 0.000000e+00, -0.000000e+00, float 0x7FF8000000000000, float 0x7FF8000000000000, i8 15)
45+
results[i++] = float4(fmod(0.0f, 1.0f),
46+
fmod(-0.0f, 1.0f),
47+
fmod(5.5f, 0.0f),
48+
fmod(-5.5f, 0.0f));
49+
50+
#endif // SPECIALS
51+
52+
#ifdef NO_FOLD
53+
// Currently, we rely on constant folding of DXIL ops to get rid of illegal
54+
// double overloads. If this doesn't happen, we expect a validation error.
55+
// Ternary operator can return literal type, while not being foldable due
56+
// non-constant condition.
57+
// NO_FOLD: error: validation errors
58+
// NO_FOLD: error: DXIL intrinsic overload must be valid.
59+
float result = fmod(-5.5, b ? 1.5 : 0.5);
60+
results[i++] = float4(result, 0, 0, 0);
61+
#endif // NO_FOLD
62+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %dxc -T vs_6_0 %s -E main | FileCheck %s
2+
// RUN: not %dxc -T vs_6_0 %s -E main -DNO_FOLD 2>&1 | FileCheck %s --check-prefixes=NO_FOLD
3+
4+
// The code path generates invalid overload. The invalid overload will either be
5+
// constant folded away, or caught by the validator.
6+
7+
// Ensure length is constant evaluated during codegen, or dxil const eval
8+
// TODO: handle fp specials properly, tracked with https://github.com/microsoft/DirectXShaderCompiler/issues/6567
9+
10+
RWBuffer<float4> results : register(u0);
11+
12+
[shader("vertex")]
13+
void main(bool b : B) {
14+
uint i = 0;
15+
16+
// Literal float
17+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 0, i32 undef, float 0x3FE6A09E60000000, float 0x4004C8DC20000000, float 0.000000e+00, float 0.000000e+00, i8 15)
18+
results[i++] = float4(length(0.5.xx),
19+
length(-1.5.xxx),
20+
length(0.0.xxxx),
21+
length(-0.0.xxxx));
22+
23+
// Explicit float
24+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 1, i32 undef, float 0x3FE6A09E60000000, float 0x4004C8DC20000000, float 0.000000e+00, float 0.000000e+00, i8 15)
25+
results[i++] = float4(length(0.5F.xx),
26+
length(-1.5F.xxx),
27+
length(0.0F.xxxx),
28+
length(-0.0F.xxxx));
29+
30+
#ifdef NO_FOLD
31+
// Currently, we rely on constant folding of DXIL ops to get rid of illegal
32+
// double overloads. If this doesn't happen, we expect a validation error.
33+
// Ternary operator can return literal type, while not being foldable due
34+
// non-constant condition.
35+
// NO_FOLD: error: validation errors
36+
// NO_FOLD: error: DXIL intrinsic overload must be valid.
37+
float result = length((b ? 1.5 : 0.5).xxx);
38+
results[i++] = float4(result, 0, 0, 0);
39+
#endif // NO_FOLD
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %dxc -T vs_6_0 %s -E main | FileCheck %s
2+
// RUN: not %dxc -T vs_6_0 %s -E main -DNO_FOLD 2>&1 | FileCheck %s --check-prefixes=NO_FOLD
3+
4+
// The code path generates invalid overload. The invalid overload will either be
5+
// constant folded away, or caught by the validator.
6+
7+
// Ensure normalize is constant evaluated during codegen, or dxil const eval
8+
// TODO: handle fp specials properly, tracked with https://github.com/microsoft/DirectXShaderCompiler/issues/6567
9+
10+
11+
RWBuffer<float4> results : register(u0);
12+
13+
[shader("vertex")]
14+
void main(bool b : B) {
15+
uint i = 0;
16+
17+
// Literal float
18+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 0, i32 undef, float 0x3FE6A09E60000000, float 0xBFE279A740000000, float 0x7FF8000000000000, float 0x7FF8000000000000, i8 15)
19+
results[i++] = float4(normalize(0.5.xx).x,
20+
normalize(-1.5.xxx).x,
21+
normalize(0.0.xxxx).x,
22+
normalize(-0.0.xxxx).x);
23+
24+
// Explicit float
25+
// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %{{.+}}, i32 1, i32 undef, float 0x3FE6A09E60000000, float 0xBFE279A740000000, float 0x7FF8000000000000, float 0x7FF8000000000000, i8 15)
26+
results[i++] = float4(normalize(0.5F.xx).x,
27+
normalize(-1.5F.xxx).x,
28+
normalize(0.0F.xxxx).x,
29+
normalize(-0.0F.xxxx).x);
30+
31+
#ifdef NO_FOLD
32+
// Currently, we rely on constant folding of DXIL ops to get rid of illegal
33+
// double overloads. If this doesn't happen, we expect a validation error.
34+
// Ternary operator can return literal type, while not being foldable due
35+
// non-constant condition.
36+
// NO_FOLD: error: validation errors
37+
// NO_FOLD: error: DXIL intrinsic overload must be valid.
38+
results[i++] = normalize((b ? 1.25 : 2.5).xxxx);
39+
#endif // NO_FOLD
40+
}

0 commit comments

Comments
 (0)