xref: /llvm-project/clang/test/CodeGenHLSL/builtins/mad.hlsl (revision 762f1b17b2815ccdfb4e5cb5412cb6210db92f73)
1// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4// RUN:   --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF
5// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
6// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
7// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF
8
9// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
10// RUN:   spirv-unknown-vulkan-compute %s -fnative-half-type \
11// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
12// RUN:   --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK
13// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
14// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
15// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_CHECK
16
17#ifdef __HLSL_ENABLE_16_BIT
18// DXIL_NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2)
19// DXIL_NATIVE_HALF: ret i16 %dx.umad
20// SPIR_NATIVE_HALF: mul nuw i16 %{{.*}}, %{{.*}}
21// SPIR_NATIVE_HALF: add nuw i16 %{{.*}}, %{{.*}}
22uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); }
23
24// DXIL_NATIVE_HALF: %dx.umad = call <2 x i16>  @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2)
25// DXIL_NATIVE_HALF: ret <2 x i16> %dx.umad
26// SPIR_NATIVE_HALF: mul nuw <2 x i16>  %{{.*}}, %{{.*}}
27// SPIR_NATIVE_HALF: add nuw <2 x i16>  %{{.*}}, %{{.*}}
28uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); }
29
30// DXIL_NATIVE_HALF: %dx.umad = call <3 x i16>  @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2)
31// DXIL_NATIVE_HALF: ret <3 x i16> %dx.umad
32// SPIR_NATIVE_HALF: mul nuw <3 x i16>  %{{.*}}, %{{.*}}
33// SPIR_NATIVE_HALF: add nuw <3 x i16>  %{{.*}}, %{{.*}}
34uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); }
35
36// DXIL_NATIVE_HALF: %dx.umad = call <4 x i16>  @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2)
37// DXIL_NATIVE_HALF: ret <4 x i16> %dx.umad
38// SPIR_NATIVE_HALF: mul nuw <4 x i16>  %{{.*}}, %{{.*}}
39// SPIR_NATIVE_HALF: add nuw <4 x i16>  %{{.*}}, %{{.*}}
40uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); }
41
42// DXIL_NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2)
43// DXIL_NATIVE_HALF: ret i16 %dx.imad
44// SPIR_NATIVE_HALF: mul nsw i16 %{{.*}}, %{{.*}}
45// SPIR_NATIVE_HALF: add nsw i16 %{{.*}}, %{{.*}}
46int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); }
47
48// DXIL_NATIVE_HALF: %dx.imad = call <2 x i16>  @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2)
49// DXIL_NATIVE_HALF: ret <2 x i16> %dx.imad
50// SPIR_NATIVE_HALF: mul nsw <2 x i16>  %{{.*}}, %{{.*}}
51// SPIR_NATIVE_HALF: add nsw <2 x i16>  %{{.*}}, %{{.*}}
52int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); }
53
54// DXIL_NATIVE_HALF: %dx.imad = call <3 x i16>  @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2)
55// DXIL_NATIVE_HALF: ret <3 x i16> %dx.imad
56// SPIR_NATIVE_HALF: mul nsw <3 x i16>  %{{.*}}, %{{.*}}
57// SPIR_NATIVE_HALF: add nsw <3 x i16>  %{{.*}}, %{{.*}}
58int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); }
59
60// DXIL_NATIVE_HALF: %dx.imad = call <4 x i16>  @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2)
61// DXIL_NATIVE_HALF: ret <4 x i16> %dx.imad
62// SPIR_NATIVE_HALF: mul nsw <4 x i16>  %{{.*}}, %{{.*}}
63// SPIR_NATIVE_HALF: add nsw <4 x i16>  %{{.*}}, %{{.*}}
64int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); }
65#endif // __HLSL_ENABLE_16_BIT
66
67// NATIVE_HALF: %[[p0:.*]] = load half, ptr %p0.addr, align 2
68// NATIVE_HALF: %[[p1:.*]] = load half, ptr %p1.addr, align 2
69// NATIVE_HALF: %[[p2:.*]] = load half, ptr %p2.addr, align 2
70// NATIVE_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn half @llvm.fmuladd.f16(half %[[p0]], half %[[p1]], half %[[p2]])
71// NATIVE_HALF: ret half %hlsl.fmad
72// NO_HALF: %[[p0:.*]] = load float, ptr %p0.addr, align 4
73// NO_HALF: %[[p1:.*]] = load float, ptr %p1.addr, align 4
74// NO_HALF: %[[p2:.*]] = load float, ptr %p2.addr, align 4
75// NO_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn float @llvm.fmuladd.f32(float %[[p0]], float %[[p1]], float %[[p2]])
76// NO_HALF: ret float %hlsl.fmad
77half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); }
78
79// NATIVE_HALF: %[[p0:.*]] = load <2 x half>, ptr %p0.addr, align 4
80// NATIVE_HALF: %[[p1:.*]] = load <2 x half>, ptr %p1.addr, align 4
81// NATIVE_HALF: %[[p2:.*]] = load <2 x half>, ptr %p2.addr, align 4
82// NATIVE_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <2 x half>  @llvm.fmuladd.v2f16(<2 x half> %[[p0]], <2 x half> %[[p1]], <2 x half> %[[p2]])
83// NATIVE_HALF: ret <2 x half> %hlsl.fmad
84// NO_HALF: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8
85// NO_HALF: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8
86// NO_HALF: %[[p2:.*]] = load <2 x float>, ptr %p2.addr, align 8
87// NO_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %[[p2]])
88// NO_HALF: ret <2 x float> %hlsl.fmad
89half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); }
90
91// NATIVE_HALF: %[[p0:.*]] = load <3 x half>, ptr %p0.addr, align 8
92// NATIVE_HALF: %[[p1:.*]] = load <3 x half>, ptr %p1.addr, align 8
93// NATIVE_HALF: %[[p2:.*]] = load <3 x half>, ptr %p2.addr, align 8
94// NATIVE_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <3 x half>  @llvm.fmuladd.v3f16(<3 x half> %[[p0]], <3 x half> %[[p1]], <3 x half> %[[p2]])
95// NATIVE_HALF: ret <3 x half> %hlsl.fmad
96// NO_HALF: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16
97// NO_HALF: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16
98// NO_HALF: %[[p2:.*]] = load <3 x float>, ptr %p2.addr, align 16
99// NO_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %[[p2]])
100// NO_HALF: ret <3 x float> %hlsl.fmad
101half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); }
102
103// NATIVE_HALF: %[[p0:.*]] = load <4 x half>, ptr %p0.addr, align 8
104// NATIVE_HALF: %[[p1:.*]] = load <4 x half>, ptr %p1.addr, align 8
105// NATIVE_HALF: %[[p2:.*]] = load <4 x half>, ptr %p2.addr, align 8
106// NATIVE_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <4 x half>  @llvm.fmuladd.v4f16(<4 x half> %[[p0]], <4 x half> %[[p1]], <4 x half> %[[p2]])
107// NATIVE_HALF: ret <4 x half> %hlsl.fmad
108// NO_HALF: %[[p0:.*]] = load <4 x float>, ptr %p0.addr, align 16
109// NO_HALF: %[[p1:.*]] = load <4 x float>, ptr %p1.addr, align 16
110// NO_HALF: %[[p2:.*]] = load <4 x float>, ptr %p2.addr, align 16
111// NO_HALF: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <4 x float>  @llvm.fmuladd.v4f32(<4 x float> %[[p0]], <4 x float> %[[p1]], <4 x float> %[[p2]])
112// NO_HALF: ret <4 x float> %hlsl.fmad
113half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); }
114
115// CHECK: %[[p0:.*]] = load float, ptr %p0.addr, align 4
116// CHECK: %[[p1:.*]] = load float, ptr %p1.addr, align 4
117// CHECK: %[[p2:.*]] = load float, ptr %p2.addr, align 4
118// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn float @llvm.fmuladd.f32(float %[[p0]], float %[[p1]], float %[[p2]])
119// CHECK: ret float %hlsl.fmad
120float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); }
121
122// CHECK: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8
123// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8
124// CHECK: %[[p2:.*]] = load <2 x float>, ptr %p2.addr, align 8
125// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %[[p2]])
126// CHECK: ret <2 x float> %hlsl.fmad
127float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); }
128
129// CHECK: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16
130// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16
131// CHECK: %[[p2:.*]] = load <3 x float>, ptr %p2.addr, align 16
132// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %[[p2]])
133// CHECK: ret <3 x float> %hlsl.fmad
134float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); }
135
136// CHECK: %[[p0:.*]] = load <4 x float>, ptr %p0.addr, align 16
137// CHECK: %[[p1:.*]] = load <4 x float>, ptr %p1.addr, align 16
138// CHECK: %[[p2:.*]] = load <4 x float>, ptr %p2.addr, align 16
139// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <4 x float>  @llvm.fmuladd.v4f32(<4 x float> %[[p0]], <4 x float> %[[p1]], <4 x float> %[[p2]])
140// CHECK: ret <4 x float> %hlsl.fmad
141float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }
142
143// CHECK: %[[p0:.*]] = load double, ptr %p0.addr, align 8
144// CHECK: %[[p1:.*]] = load double, ptr %p1.addr, align 8
145// CHECK: %[[p2:.*]] = load double, ptr %p2.addr, align 8
146// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn double @llvm.fmuladd.f64(double %[[p0]], double %[[p1]], double %[[p2]])
147// CHECK: ret double %hlsl.fmad
148double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); }
149
150// CHECK: %[[p0:.*]] = load <2 x double>, ptr %p0.addr, align 16
151// CHECK: %[[p1:.*]] = load <2 x double>, ptr %p1.addr, align 16
152// CHECK: %[[p2:.*]] = load <2 x double>, ptr %p2.addr, align 16
153// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <2 x double>  @llvm.fmuladd.v2f64(<2 x double> %[[p0]], <2 x double> %[[p1]], <2 x double> %[[p2]])
154// CHECK: ret <2 x double> %hlsl.fmad
155double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); }
156
157// CHECK: %[[p0:.*]] = load <3 x double>, ptr %p0.addr, align 32
158// CHECK: %[[p1:.*]] = load <3 x double>, ptr %p1.addr, align 32
159// CHECK: %[[p2:.*]] = load <3 x double>, ptr %p2.addr, align 32
160// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <3 x double>  @llvm.fmuladd.v3f64(<3 x double> %[[p0]], <3 x double> %[[p1]], <3 x double> %[[p2]])
161// CHECK: ret <3 x double> %hlsl.fmad
162double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); }
163
164// CHECK: %[[p0:.*]] = load <4 x double>, ptr %p0.addr, align 32
165// CHECK: %[[p1:.*]] = load <4 x double>, ptr %p1.addr, align 32
166// CHECK: %[[p2:.*]] = load <4 x double>, ptr %p2.addr, align 32
167// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <4 x double>  @llvm.fmuladd.v4f64(<4 x double> %[[p0]], <4 x double> %[[p1]], <4 x double> %[[p2]])
168// CHECK: ret <4 x double> %hlsl.fmad
169double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); }
170
171// DXIL_CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2)
172// DXIL_CHECK: ret i32 %dx.imad
173// SPIR_CHECK: mul nsw i32 %{{.*}}, %{{.*}}
174// SPIR_CHECK: add nsw i32 %{{.*}}, %{{.*}}
175int test_mad_int(int p0, int p1, int p2) { return mad(p0, p1, p2); }
176
177// DXIL_CHECK: %dx.imad = call <2 x i32>  @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2)
178// DXIL_CHECK: ret <2 x i32> %dx.imad
179// SPIR_CHECK: mul nsw <2 x i32>  %{{.*}}, %{{.*}}
180// SPIR_CHECK: add nsw <2 x i32>  %{{.*}}, %{{.*}}
181int2 test_mad_int2(int2 p0, int2 p1, int2 p2) { return mad(p0, p1, p2); }
182
183// DXIL_CHECK: %dx.imad = call <3 x i32>  @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2)
184// DXIL_CHECK: ret <3 x i32> %dx.imad
185// SPIR_CHECK: mul nsw <3 x i32>  %{{.*}}, %{{.*}}
186// SPIR_CHECK: add nsw <3 x i32>  %{{.*}}, %{{.*}}
187int3 test_mad_int3(int3 p0, int3 p1, int3 p2) { return mad(p0, p1, p2); }
188
189// DXIL_CHECK: %dx.imad = call <4 x i32>  @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2)
190// DXIL_CHECK: ret <4 x i32> %dx.imad
191// SPIR_CHECK: mul nsw <4 x i32>  %{{.*}}, %{{.*}}
192// SPIR_CHECK: add nsw <4 x i32>  %{{.*}}, %{{.*}}
193int4 test_mad_int4(int4 p0, int4 p1, int4 p2) { return mad(p0, p1, p2); }
194
195// DXIL_CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2)
196// DXIL_CHECK: ret i64 %dx.imad
197// SPIR_CHECK: mul nsw i64 %{{.*}}, %{{.*}}
198// SPIR_CHECK: add nsw i64 %{{.*}}, %{{.*}}
199int64_t test_mad_int64_t(int64_t p0, int64_t p1, int64_t p2) { return mad(p0, p1, p2); }
200
201// DXIL_CHECK: %dx.imad = call <2 x i64>  @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2)
202// DXIL_CHECK: ret <2 x i64> %dx.imad
203// SPIR_CHECK: mul nsw <2 x i64>  %{{.*}}, %{{.*}}
204// SPIR_CHECK: add nsw <2 x i64>  %{{.*}}, %{{.*}}
205int64_t2 test_mad_int64_t2(int64_t2 p0, int64_t2 p1, int64_t2 p2) { return mad(p0, p1, p2); }
206
207// DXIL_CHECK: %dx.imad = call <3 x i64>  @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2)
208// DXIL_CHECK: ret <3 x i64> %dx.imad
209// SPIR_CHECK: mul nsw <3 x i64>  %{{.*}}, %{{.*}}
210// SPIR_CHECK: add nsw <3 x i64>  %{{.*}}, %{{.*}}
211int64_t3 test_mad_int64_t3(int64_t3 p0, int64_t3 p1, int64_t3 p2) { return mad(p0, p1, p2); }
212
213// DXIL_CHECK: %dx.imad = call <4 x i64>  @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2)
214// DXIL_CHECK: ret <4 x i64> %dx.imad
215// SPIR_CHECK: mul nsw <4 x i64>  %{{.*}}, %{{.*}}
216// SPIR_CHECK: add nsw <4 x i64>  %{{.*}}, %{{.*}}
217int64_t4 test_mad_int64_t4(int64_t4 p0, int64_t4 p1, int64_t4 p2) { return mad(p0, p1, p2); }
218
219// DXIL_CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2)
220// DXIL_CHECK: ret i32 %dx.umad
221// SPIR_CHECK: mul nuw i32 %{{.*}}, %{{.*}}
222// SPIR_CHECK: add nuw i32 %{{.*}}, %{{.*}}
223uint test_mad_uint(uint p0, uint p1, uint p2) { return mad(p0, p1, p2); }
224
225// DXIL_CHECK: %dx.umad = call <2 x i32>  @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2)
226// DXIL_CHECK: ret <2 x i32> %dx.umad
227// SPIR_CHECK: mul nuw <2 x i32>  %{{.*}}, %{{.*}}
228// SPIR_CHECK: add nuw <2 x i32>  %{{.*}}, %{{.*}}
229uint2 test_mad_uint2(uint2 p0, uint2 p1, uint2 p2) { return mad(p0, p1, p2); }
230
231// DXIL_CHECK: %dx.umad = call <3 x i32>  @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2)
232// DXIL_CHECK: ret <3 x i32> %dx.umad
233// SPIR_CHECK: mul nuw <3 x i32>  %{{.*}}, %{{.*}}
234// SPIR_CHECK: add nuw <3 x i32>  %{{.*}}, %{{.*}}
235uint3 test_mad_uint3(uint3 p0, uint3 p1, uint3 p2) { return mad(p0, p1, p2); }
236
237// DXIL_CHECK: %dx.umad = call <4 x i32>  @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2)
238// DXIL_CHECK: ret <4 x i32> %dx.umad
239// SPIR_CHECK: mul nuw <4 x i32>  %{{.*}}, %{{.*}}
240// SPIR_CHECK: add nuw <4 x i32>  %{{.*}}, %{{.*}}
241uint4 test_mad_uint4(uint4 p0, uint4 p1, uint4 p2) { return mad(p0, p1, p2); }
242
243// DXIL_CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2)
244// DXIL_CHECK: ret i64 %dx.umad
245// SPIR_CHECK: mul nuw i64 %{{.*}}, %{{.*}}
246// SPIR_CHECK: add nuw i64 %{{.*}}, %{{.*}}
247uint64_t test_mad_uint64_t(uint64_t p0, uint64_t p1, uint64_t p2) { return mad(p0, p1, p2); }
248
249// DXIL_CHECK: %dx.umad = call <2 x i64>  @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2)
250// DXIL_CHECK: ret <2 x i64> %dx.umad
251// SPIR_CHECK: mul nuw <2 x i64>  %{{.*}}, %{{.*}}
252// SPIR_CHECK: add nuw <2 x i64>  %{{.*}}, %{{.*}}
253uint64_t2 test_mad_uint64_t2(uint64_t2 p0, uint64_t2 p1, uint64_t2 p2) { return mad(p0, p1, p2); }
254
255// DXIL_CHECK: %dx.umad = call <3 x i64>  @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2)
256// DXIL_CHECK: ret <3 x i64> %dx.umad
257// SPIR_CHECK: mul nuw <3 x i64>  %{{.*}}, %{{.*}}
258// SPIR_CHECK: add nuw <3 x i64>  %{{.*}}, %{{.*}}
259uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return mad(p0, p1, p2); }
260
261// DXIL_CHECK: %dx.umad = call <4 x i64>  @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2)
262// DXIL_CHECK: ret <4 x i64> %dx.umad
263// SPIR_CHECK: mul nuw <4 x i64>  %{{.*}}, %{{.*}}
264// SPIR_CHECK: add nuw <4 x i64>  %{{.*}}, %{{.*}}
265uint64_t4 test_mad_uint64_t4(uint64_t4 p0, uint64_t4 p1, uint64_t4 p2) { return mad(p0, p1, p2); }
266