Skip to content

Commit fa77c53

Browse files
authored
Merge branch 'main' into X86lowerFPToIntToFP-UI2FP
2 parents 3a5dc16 + 19a58a5 commit fa77c53

File tree

7 files changed

+273
-159
lines changed

7 files changed

+273
-159
lines changed
Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,112 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
2-
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
2+
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPV
33

44
// NOTE: SPIRV codegen for resource methods is not yet implemented
55

66
StructuredBuffer<float> SB1 : register(t0);
77
RWStructuredBuffer<float> RWSB1 : register(u0);
8-
RWStructuredBuffer<float> RWSB2 : register(u1);
8+
RWStructuredBuffer<uint4> RWSB2 : register(u1);
99
AppendStructuredBuffer<float> ASB : register(u2);
10-
ConsumeStructuredBuffer<float> CSB : register(u3);
10+
ConsumeStructuredBuffer<double> CSB : register(u3);
1111

12-
// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
13-
// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
14-
// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
15-
// CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
12+
// DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
13+
// DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
14+
// DXIL: %"class.hlsl::RWStructuredBuffer.0" = type { target("dx.RawBuffer", <4 x i32>, 1, 0), target("dx.RawBuffer", <4 x i32>, 1, 0) }
15+
// DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
16+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", double, 1, 0), target("dx.RawBuffer", double, 1, 0) }
1617

1718
export int TestIncrementCounter() {
1819
return RWSB1.IncrementCounter();
1920
}
2021

21-
// CHECK: define noundef i32 @_Z20TestIncrementCounterv()
22-
// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1)
23-
// CHECK-DXIL: ret i32 %[[INDEX]]
22+
// CHECK: define noundef i32 @TestIncrementCounter()()
23+
// CHECK: call noundef i32 @hlsl::RWStructuredBuffer<float>::IncrementCounter()(ptr {{.*}} @RWSB1)
24+
// CHECK: ret
25+
26+
// CHECK: define {{.*}} noundef i32 @hlsl::RWStructuredBuffer<float>::IncrementCounter()(ptr {{.*}} %this)
27+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
28+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
29+
// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i8 1)
30+
// CHECK-NEXT: ret i32 %[[COUNTER]]
31+
2432
export int TestDecrementCounter() {
2533
return RWSB2.DecrementCounter();
2634
}
35+
// CHECK: define {{.*}} i32 @TestDecrementCounter()()
36+
// CHECK: call noundef i32 @hlsl::RWStructuredBuffer<unsigned int vector[4]>::DecrementCounter()(ptr {{.*}} @RWSB2)
37+
// CHECK: ret
2738

28-
// CHECK: define noundef i32 @_Z20TestDecrementCounterv()
29-
// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1)
30-
// CHECK-DXIL: ret i32 %[[INDEX]]
39+
// CHECK: define {{.*}} noundef i32 @hlsl::RWStructuredBuffer<unsigned int vector[4]>::DecrementCounter()(ptr {{.*}} %this)
40+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
41+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle
42+
// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i8 -1)
43+
// CHECK-NEXT: ret i32 %[[COUNTER]]
3144

3245
export void TestAppend(float value) {
3346
ASB.Append(value);
3447
}
3548

36-
// CHECK: define void @_Z10TestAppendf(float noundef nofpclass(nan inf) %value)
37-
// CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %value.addr, align 4
38-
// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1)
39-
// CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %[[INDEX]])
40-
// CHECK-DXIL: store float %[[VALUE]], ptr %[[RESPTR]], align 4
49+
// CHECK: define void @TestAppend(float)(float {{.*}} %value)
50+
// CHECK: call void @hlsl::AppendStructuredBuffer<float>::Append(float)(ptr {{.*}} @ASB, float noundef nofpclass(nan inf) %0)
51+
// CHECK: ret void
52+
53+
// CHECK: define {{.*}} void @hlsl::AppendStructuredBuffer<float>::Append(float)(ptr {{.*}} %this, float noundef nofpclass(nan inf) %value)
54+
// CHECK: %[[VALUE:.*]] = load float, ptr %value.addr
55+
// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
56+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
57+
// CHECK-NEXT: %__handle2 = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
58+
// DXIL-NEXT: %[[HANDLE2:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle2
59+
// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE2]], i8 1)
60+
// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i32 %[[COUNTER]])
61+
// CHECK-NEXT: store float %[[VALUE]], ptr %[[PTR]]
62+
// CHECK-NEXT: ret void
4163

42-
export float TestConsume() {
64+
export double TestConsume() {
4365
return CSB.Consume();
4466
}
45-
46-
// CHECK: define noundef nofpclass(nan inf) float @_Z11TestConsumev()
47-
// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %1, i8 -1)
48-
// CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %0, i32 %[[INDEX]])
49-
// CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %[[RESPTR]], align 4
50-
// CHECK-DXIL: ret float %[[VALUE]]
67+
// CHECK: define {{.*}} double @TestConsume()()
68+
// CHECK: call {{.*}} double @hlsl::ConsumeStructuredBuffer<double>::Consume()(ptr {{.*}} @CSB)
69+
// CHECK: ret double
70+
71+
// CHECK: define {{.*}} double @hlsl::ConsumeStructuredBuffer<double>::Consume()(ptr {{.*}} %this)
72+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
73+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle
74+
// CHECK-NEXT: %__handle2 = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
75+
// DXIL-NEXT: %[[HANDLE2:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle2
76+
// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE2]], i8 -1)
77+
// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 %[[COUNTER]])
78+
// CHECK-NEXT: %[[VAL:.*]] = load double, ptr %[[PTR]], align 8
79+
// CHECK-NEXT: ret double %[[VAL]]
5180

5281
export float TestLoad() {
5382
return RWSB1.Load(1) + SB1.Load(2);
5483
}
5584

56-
// CHECK: define noundef nofpclass(nan inf) float @_Z8TestLoadv()
57-
// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %{{[0-9]+}})
58-
// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]]
59-
// CHECK: %[[PTR2:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %{{[0-9]+}}, i32 %{{[0-9]+}})
60-
// CHECK: %[[VALUE2:.*]] = load float, ptr %[[PTR2]]
85+
// CHECK: define noundef nofpclass(nan inf) float @TestLoad()()
86+
// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1)
87+
// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @SB1, i32 noundef 2)
88+
// CHECK: add
89+
// CHECK: ret float
90+
91+
// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
92+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
93+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
94+
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
95+
// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
96+
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
97+
// CHECK-NEXT: ret float %[[VAL]]
98+
99+
// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
100+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
101+
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
102+
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
103+
// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 %[[INDEX]])
104+
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
105+
// CHECK-NEXT: ret float %[[VAL]]
61106

62-
// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
63-
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32)
64-
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
107+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
108+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i8)
109+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32)
110+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i8)
111+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
112+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,71 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
2-
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-pixel -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
2+
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-pixel -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPV
33

44
// NOTE: SPIRV codegen for resource methods is not yet implemented
55

6-
RWStructuredBuffer<float> RWSB1, RWSB2;
7-
RasterizerOrderedStructuredBuffer<float> ROSB1, ROSB2;
6+
RasterizerOrderedStructuredBuffer<float> ROSB1;
7+
RasterizerOrderedStructuredBuffer<int2> ROSB2;
88

9-
// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) }
9+
// %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1), target("dx.RawBuffer", float, 1, 1) }
10+
// %"class.hlsl::RasterizerOrderedStructuredBuffer.0" = type { target("dx.RawBuffer", <2 x i32>, 1, 1), target("dx.RawBuffer", <2 x i32>, 1, 1) }
11+
12+
// CHECK: @ROSB1 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison
13+
// CHECK: @ROSB2 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer.0" poison
1014

1115
export void TestIncrementCounter() {
12-
// CHECK: define void @_Z20TestIncrementCounterv()
13-
// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1)
14-
// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 1)
15-
RWSB1.IncrementCounter();
1616
ROSB1.IncrementCounter();
1717
}
1818

19+
// CHECK: define void @TestIncrementCounter()()
20+
// CHECK: call noundef i32 @hlsl::RasterizerOrderedStructuredBuffer<float>::IncrementCounter()(ptr {{.*}} @ROSB1)
21+
// CHECK-NEXT: ret void
22+
23+
// CHECK: define {{.*}} i32 @hlsl::RasterizerOrderedStructuredBuffer<float>::IncrementCounter()(ptr {{.*}} %this)
24+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
25+
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
26+
// DXIL-NEXT: %[[VAL:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i8 1)
27+
// CHECK-NEXT: ret i32 %[[VAL]]
28+
1929
export void TestDecrementCounter() {
20-
// CHECK: define void @_Z20TestDecrementCounterv()
21-
// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1)
22-
// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 -1)
23-
RWSB2.DecrementCounter();
2430
ROSB2.DecrementCounter();
2531
}
2632

33+
// CHECK: define void @TestDecrementCounter()()
34+
// CHECK: call noundef i32 @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::DecrementCounter()(ptr {{.*}} @ROSB2)
35+
// CHECK-NEXT: ret void
36+
37+
// CHECK: define {{.*}} i32 @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::DecrementCounter()(ptr {{.*}} %this)
38+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
39+
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
40+
// DXIL-NEXT: %[[VAL:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i8 -1)
41+
// CHECK-NEXT: ret i32 %[[VAL]]
42+
2743
export float TestLoad() {
28-
return ROSB1.Load(10);
44+
return ROSB1.Load(10).x + ROSB2.Load(20).x;
2945
}
3046

31-
// CHECK: define noundef nofpclass(nan inf) float @_Z8TestLoadv()
32-
// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i32 %{{[0-9]+}})
33-
// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]]
47+
// CHECK: define {{.*}} float @TestLoad()()
48+
// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @ROSB1, i32 noundef 10)
49+
// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int)(ptr {{.*}} @ROSB2, i32 noundef 20)
50+
// CHECK: ret
51+
52+
// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %Index)
53+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr {{.*}}, i32 0, i32 0
54+
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
55+
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
56+
// DXIL-NEXT: %[[BUFPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 %[[INDEX]])
57+
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[BUFPTR]]
58+
// CHECK-NEXT: ret float %[[VAL]]
59+
60+
// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int)(ptr {{.*}} %Index)
61+
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr {{.*}}, i32 0, i32 0
62+
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
63+
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
64+
// DXIL-NEXT: %[[BUFPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 %[[INDEX]])
65+
// CHECK-NEXT: %[[VAL:.*]] = load <2 x i32>, ptr %[[BUFPTR]]
66+
// CHECK-NEXT: ret <2 x i32> %[[VAL]]
3467

35-
// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
36-
// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8)
37-
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
68+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8)
69+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i8)
70+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
71+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,29 @@ static MachineBasicBlock *LowerMemcpy(MachineInstr &MI, DebugLoc DL,
601601
MachineOperand Src = MI.getOperand(3);
602602
MachineOperand Len = MI.getOperand(4);
603603

604+
// If the length is a constant, we don't actually need the check.
605+
if (MachineInstr *Def = MRI.getVRegDef(Len.getReg())) {
606+
if (Def->getOpcode() == WebAssembly::CONST_I32 ||
607+
Def->getOpcode() == WebAssembly::CONST_I64) {
608+
if (Def->getOperand(1).getImm() == 0) {
609+
// A zero-length memcpy is a no-op.
610+
MI.eraseFromParent();
611+
return BB;
612+
}
613+
// A non-zero-length memcpy doesn't need a zero check.
614+
unsigned MemoryCopy =
615+
Int64 ? WebAssembly::MEMORY_COPY_A64 : WebAssembly::MEMORY_COPY_A32;
616+
BuildMI(*BB, MI, DL, TII.get(MemoryCopy))
617+
.add(DstMem)
618+
.add(SrcMem)
619+
.add(Dst)
620+
.add(Src)
621+
.add(Len);
622+
MI.eraseFromParent();
623+
return BB;
624+
}
625+
}
626+
604627
// We're going to add an extra use to `Len` to test if it's zero; that
605628
// use shouldn't be a kill, even if the original use is.
606629
MachineOperand NoKillLen = Len;
@@ -669,6 +692,28 @@ static MachineBasicBlock *LowerMemset(MachineInstr &MI, DebugLoc DL,
669692
MachineOperand Val = MI.getOperand(2);
670693
MachineOperand Len = MI.getOperand(3);
671694

695+
// If the length is a constant, we don't actually need the check.
696+
if (MachineInstr *Def = MRI.getVRegDef(Len.getReg())) {
697+
if (Def->getOpcode() == WebAssembly::CONST_I32 ||
698+
Def->getOpcode() == WebAssembly::CONST_I64) {
699+
if (Def->getOperand(1).getImm() == 0) {
700+
// A zero-length memset is a no-op.
701+
MI.eraseFromParent();
702+
return BB;
703+
}
704+
// A non-zero-length memset doesn't need a zero check.
705+
unsigned MemoryFill =
706+
Int64 ? WebAssembly::MEMORY_FILL_A64 : WebAssembly::MEMORY_FILL_A32;
707+
BuildMI(*BB, MI, DL, TII.get(MemoryFill))
708+
.add(Mem)
709+
.add(Dst)
710+
.add(Val)
711+
.add(Len);
712+
MI.eraseFromParent();
713+
return BB;
714+
}
715+
}
716+
672717
// We're going to add an extra use to `Len` to test if it's zero; that
673718
// use shouldn't be a kill, even if the original use is.
674719
MachineOperand NoKillLen = Len;

0 commit comments

Comments
 (0)