1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=nsan -nsan-shadow-type-mapping=dqq -nsan-truncate-fcmp-eq=false -S %s | FileCheck %s --check-prefixes=CHECK,DQQ
3 ; RUN: opt -passes=nsan -nsan-shadow-type-mapping=dlq -nsan-truncate-fcmp-eq=false -S %s | FileCheck %s --check-prefixes=CHECK,DLQ
5 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
7 declare float @declaration_only(float %a) sanitize_numerical_stability
9 ; Tests with simple control flow.
11 @float_const = private unnamed_addr constant float 0.5
12 @x86_fp80_const = private unnamed_addr constant x86_fp80 0xK3FC9E69594BEC44DE000
13 @double_const = private unnamed_addr constant double 0.5
16 define float @return_param_float(float %a) sanitize_numerical_stability {
17 ; CHECK-LABEL: @return_param_float(
19 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
20 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @return_param_float to i64)
21 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
22 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[A:%.*]] to double
23 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
24 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
25 ; CHECK-NEXT: [[TMP5:%.*]] = call i32 @__nsan_internal_check_float_d(float [[A]], double [[TMP4]], i32 1, i64 0)
26 ; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 1
27 ; CHECK-NEXT: [[TMP7:%.*]] = fpext float [[A]] to double
28 ; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP6]], double [[TMP7]], double [[TMP4]]
29 ; CHECK-NEXT: store i64 ptrtoint (ptr @return_param_float to i64), ptr @__nsan_shadow_ret_tag, align 8
30 ; CHECK-NEXT: store double [[TMP8]], ptr @__nsan_shadow_ret_ptr, align 8
31 ; CHECK-NEXT: ret float [[A]]
37 ; Note that the shadow fadd should not have a `fast` flag.
38 define float @param_add_return_float(float %a) sanitize_numerical_stability {
39 ; CHECK-LABEL: @param_add_return_float(
41 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
42 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @param_add_return_float to i64)
43 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
44 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[A:%.*]] to double
45 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
46 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
47 ; CHECK-NEXT: [[B:%.*]] = fadd fast float [[A]], 1.000000e+00
48 ; CHECK-NEXT: [[TMP5:%.*]] = fadd double [[TMP4]], 1.000000e+00
49 ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_float_d(float [[B]], double [[TMP5]], i32 1, i64 0)
50 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
51 ; CHECK-NEXT: [[TMP8:%.*]] = fpext float [[B]] to double
52 ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], double [[TMP8]], double [[TMP5]]
53 ; CHECK-NEXT: store i64 ptrtoint (ptr @param_add_return_float to i64), ptr @__nsan_shadow_ret_tag, align 8
54 ; CHECK-NEXT: store double [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 8
55 ; CHECK-NEXT: ret float [[B]]
58 %b = fadd fast float %a, 1.0
62 define x86_fp80 @param_add_return_x86_fp80(x86_fp80 %a) sanitize_numerical_stability {
63 ; CHECK-LABEL: @param_add_return_x86_fp80(
65 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
66 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @param_add_return_x86_fp80 to i64)
67 ; CHECK-NEXT: [[TMP2:%.*]] = load fp128, ptr @__nsan_shadow_args_ptr, align 1
68 ; CHECK-NEXT: [[TMP3:%.*]] = fpext x86_fp80 [[A:%.*]] to fp128
69 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], fp128 [[TMP2]], fp128 [[TMP3]]
70 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
71 ; CHECK-NEXT: [[B:%.*]] = fadd x86_fp80 [[A]], 0xK3FC9E69594BEC44DE000
72 ; CHECK-NEXT: [[TMP5:%.*]] = fadd fp128 [[TMP4]], 0xLC0000000000000003FC9CD2B297D889B
73 ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[B]], fp128 [[TMP5]], i32 1, i64 0)
74 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
75 ; CHECK-NEXT: [[TMP8:%.*]] = fpext x86_fp80 [[B]] to fp128
76 ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], fp128 [[TMP8]], fp128 [[TMP5]]
77 ; CHECK-NEXT: store i64 ptrtoint (ptr @param_add_return_x86_fp80 to i64), ptr @__nsan_shadow_ret_tag, align 8
78 ; CHECK-NEXT: store fp128 [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 16
79 ; CHECK-NEXT: ret x86_fp80 [[B]]
82 %b = fadd x86_fp80 %a, 0xK3FC9E69594BEC44DE000
86 define double @param_add_return_double(double %a) sanitize_numerical_stability {
87 ; DQQ-LABEL: @param_add_return_double(
89 ; DQQ-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
90 ; DQQ-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @param_add_return_double to i64)
91 ; DQQ-NEXT: [[TMP2:%.*]] = load fp128, ptr @__nsan_shadow_args_ptr, align 1
92 ; DQQ-NEXT: [[TMP3:%.*]] = fpext double [[A:%.*]] to fp128
93 ; DQQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], fp128 [[TMP2]], fp128 [[TMP3]]
94 ; DQQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
95 ; DQQ-NEXT: [[B:%.*]] = fadd double [[A]], 1.000000e+00
96 ; DQQ-NEXT: [[TMP5:%.*]] = fadd fp128 [[TMP4]], 0xL00000000000000003FFF000000000000
97 ; DQQ-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_double_q(double [[B]], fp128 [[TMP5]], i32 1, i64 0)
98 ; DQQ-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
99 ; DQQ-NEXT: [[TMP8:%.*]] = fpext double [[B]] to fp128
100 ; DQQ-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], fp128 [[TMP8]], fp128 [[TMP5]]
101 ; DQQ-NEXT: store i64 ptrtoint (ptr @param_add_return_double to i64), ptr @__nsan_shadow_ret_tag, align 8
102 ; DQQ-NEXT: store fp128 [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 16
103 ; DQQ-NEXT: ret double [[B]]
105 ; DLQ-LABEL: @param_add_return_double(
107 ; DLQ-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
108 ; DLQ-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @param_add_return_double to i64)
109 ; DLQ-NEXT: [[TMP2:%.*]] = load x86_fp80, ptr @__nsan_shadow_args_ptr, align 1
110 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[A:%.*]] to x86_fp80
111 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], x86_fp80 [[TMP2]], x86_fp80 [[TMP3]]
112 ; DLQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
113 ; DLQ-NEXT: [[B:%.*]] = fadd double [[A]], 1.000000e+00
114 ; DLQ-NEXT: [[TMP5:%.*]] = fadd x86_fp80 [[TMP4]], 0xK3FFF8000000000000000
115 ; DLQ-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_double_l(double [[B]], x86_fp80 [[TMP5]], i32 1, i64 0)
116 ; DLQ-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
117 ; DLQ-NEXT: [[TMP8:%.*]] = fpext double [[B]] to x86_fp80
118 ; DLQ-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], x86_fp80 [[TMP8]], x86_fp80 [[TMP5]]
119 ; DLQ-NEXT: store i64 ptrtoint (ptr @param_add_return_double to i64), ptr @__nsan_shadow_ret_tag, align 8
120 ; DLQ-NEXT: store x86_fp80 [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 16
121 ; DLQ-NEXT: ret double [[B]]
124 %b = fadd double %a, 1.0
128 define <2 x float> @return_param_add_return_float_vector(<2 x float> %a) sanitize_numerical_stability {
129 ; CHECK-LABEL: @return_param_add_return_float_vector(
131 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
132 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @return_param_add_return_float_vector to i64)
133 ; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr @__nsan_shadow_args_ptr, align 1
134 ; CHECK-NEXT: [[TMP3:%.*]] = fpext <2 x float> [[A:%.*]] to <2 x double>
135 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], <2 x double> [[TMP2]], <2 x double> [[TMP3]]
136 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
137 ; CHECK-NEXT: [[B:%.*]] = fadd <2 x float> [[A]], splat (float 1.000000e+00)
138 ; CHECK-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[TMP4]], splat (double 1.000000e+00)
139 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[B]], i64 0
140 ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[TMP5]], i64 0
141 ; CHECK-NEXT: [[TMP8:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP6]], double [[TMP7]], i32 1, i64 0)
142 ; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[B]], i64 1
143 ; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[TMP5]], i64 1
144 ; CHECK-NEXT: [[TMP11:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP9]], double [[TMP10]], i32 1, i64 0)
145 ; CHECK-NEXT: [[TMP12:%.*]] = or i32 [[TMP8]], [[TMP11]]
146 ; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP12]], 1
147 ; CHECK-NEXT: [[TMP14:%.*]] = fpext <2 x float> [[B]] to <2 x double>
148 ; CHECK-NEXT: [[TMP15:%.*]] = select i1 [[TMP13]], <2 x double> [[TMP14]], <2 x double> [[TMP5]]
149 ; CHECK-NEXT: store i64 ptrtoint (ptr @return_param_add_return_float_vector to i64), ptr @__nsan_shadow_ret_tag, align 8
150 ; CHECK-NEXT: store <2 x double> [[TMP15]], ptr @__nsan_shadow_ret_ptr, align 16
151 ; CHECK-NEXT: ret <2 x float> [[B]]
154 %b = fadd <2 x float> %a, <float 1.0, float 1.0>
158 ; TODO: This is ignored for now.
159 define [2 x float] @return_param_float_array([2 x float] %a) sanitize_numerical_stability {
160 ; CHECK-LABEL: @return_param_float_array(
162 ; CHECK-NEXT: ret [2 x float] [[A:%.*]]
168 define void @constantload_add_store_float(ptr %dst) sanitize_numerical_stability {
169 ; CHECK-LABEL: @constantload_add_store_float(
171 ; CHECK-NEXT: [[B:%.*]] = load float, ptr @float_const, align 4
172 ; CHECK-NEXT: [[TMP0:%.*]] = fpext float [[B]] to double
173 ; CHECK-NEXT: [[C:%.*]] = fadd float [[B]], 1.000000e+00
174 ; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[TMP0]], 1.000000e+00
175 ; CHECK-NEXT: [[TMP2:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_store(ptr [[DST:%.*]], i64 1)
176 ; CHECK-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[DST]] to i64
177 ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @__nsan_internal_check_float_d(float [[C]], double [[TMP1]], i32 4, i64 [[TMP3]])
178 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 1
179 ; CHECK-NEXT: [[TMP6:%.*]] = fpext float [[C]] to double
180 ; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], double [[TMP6]], double [[TMP1]]
181 ; CHECK-NEXT: store double [[TMP7]], ptr [[TMP2]], align 1
182 ; CHECK-NEXT: store float [[C]], ptr [[DST]], align 1
183 ; CHECK-NEXT: ret void
186 %b = load float, ptr @float_const
187 %c = fadd float %b, 1.0
188 store float %c, ptr %dst, align 1
192 define void @constantload_add_store_x86_fp80(ptr %dst) sanitize_numerical_stability {
193 ; CHECK-LABEL: @constantload_add_store_x86_fp80(
195 ; CHECK-NEXT: [[B:%.*]] = load x86_fp80, ptr @x86_fp80_const, align 16
196 ; CHECK-NEXT: [[TMP0:%.*]] = fpext x86_fp80 [[B]] to fp128
197 ; CHECK-NEXT: [[C:%.*]] = fadd x86_fp80 [[B]], 0xK3FC9E69594BEC44DE000
198 ; CHECK-NEXT: [[TMP1:%.*]] = fadd fp128 [[TMP0]], 0xLC0000000000000003FC9CD2B297D889B
199 ; CHECK-NEXT: [[TMP2:%.*]] = call ptr @__nsan_get_shadow_ptr_for_longdouble_store(ptr [[DST:%.*]], i64 1)
200 ; CHECK-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[DST]] to i64
201 ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[C]], fp128 [[TMP1]], i32 4, i64 [[TMP3]])
202 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 1
203 ; CHECK-NEXT: [[TMP6:%.*]] = fpext x86_fp80 [[C]] to fp128
204 ; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], fp128 [[TMP6]], fp128 [[TMP1]]
205 ; CHECK-NEXT: store fp128 [[TMP7]], ptr [[TMP2]], align 1
206 ; CHECK-NEXT: store x86_fp80 [[C]], ptr [[DST]], align 1
207 ; CHECK-NEXT: ret void
210 %b = load x86_fp80, ptr @x86_fp80_const
211 %c = fadd x86_fp80 %b, 0xK3FC9E69594BEC44DE000
212 store x86_fp80 %c, ptr %dst, align 1
216 define void @constantload_add_store_double(ptr %dst) sanitize_numerical_stability {
217 ; DQQ-LABEL: @constantload_add_store_double(
219 ; DQQ-NEXT: [[B:%.*]] = load double, ptr @double_const, align 8
220 ; DQQ-NEXT: [[TMP0:%.*]] = fpext double [[B]] to fp128
221 ; DQQ-NEXT: [[C:%.*]] = fadd double [[B]], 1.000000e+00
222 ; DQQ-NEXT: [[TMP1:%.*]] = fadd fp128 [[TMP0]], 0xL00000000000000003FFF000000000000
223 ; DQQ-NEXT: [[TMP2:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_store(ptr [[DST:%.*]], i64 1)
224 ; DQQ-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[DST]] to i64
225 ; DQQ-NEXT: [[TMP4:%.*]] = call i32 @__nsan_internal_check_double_q(double [[C]], fp128 [[TMP1]], i32 4, i64 [[TMP3]])
226 ; DQQ-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 1
227 ; DQQ-NEXT: [[TMP6:%.*]] = fpext double [[C]] to fp128
228 ; DQQ-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], fp128 [[TMP6]], fp128 [[TMP1]]
229 ; DQQ-NEXT: store fp128 [[TMP7]], ptr [[TMP2]], align 1
230 ; DQQ-NEXT: store double [[C]], ptr [[DST]], align 1
233 ; DLQ-LABEL: @constantload_add_store_double(
235 ; DLQ-NEXT: [[B:%.*]] = load double, ptr @double_const, align 8
236 ; DLQ-NEXT: [[TMP0:%.*]] = fpext double [[B]] to x86_fp80
237 ; DLQ-NEXT: [[C:%.*]] = fadd double [[B]], 1.000000e+00
238 ; DLQ-NEXT: [[TMP1:%.*]] = fadd x86_fp80 [[TMP0]], 0xK3FFF8000000000000000
239 ; DLQ-NEXT: [[TMP2:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_store(ptr [[DST:%.*]], i64 1)
240 ; DLQ-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[DST]] to i64
241 ; DLQ-NEXT: [[TMP4:%.*]] = call i32 @__nsan_internal_check_double_l(double [[C]], x86_fp80 [[TMP1]], i32 4, i64 [[TMP3]])
242 ; DLQ-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 1
243 ; DLQ-NEXT: [[TMP6:%.*]] = fpext double [[C]] to x86_fp80
244 ; DLQ-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], x86_fp80 [[TMP6]], x86_fp80 [[TMP1]]
245 ; DLQ-NEXT: store x86_fp80 [[TMP7]], ptr [[TMP2]], align 1
246 ; DLQ-NEXT: store double [[C]], ptr [[DST]], align 1
250 %b = load double, ptr @double_const
251 %c = fadd double %b, 1.0
252 store double %c, ptr %dst, align 1
256 define void @load_add_store_float(ptr %a) sanitize_numerical_stability {
257 ; CHECK-LABEL: @load_add_store_float(
259 ; CHECK-NEXT: [[B:%.*]] = load float, ptr [[A:%.*]], align 1
260 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_load(ptr [[A]], i64 1)
261 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
262 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
264 ; CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[TMP0]], align 1
265 ; CHECK-NEXT: br label [[TMP6:%.*]]
267 ; CHECK-NEXT: [[TMP5:%.*]] = fpext float [[B]] to double
268 ; CHECK-NEXT: br label [[TMP6]]
270 ; CHECK-NEXT: [[TMP7:%.*]] = phi double [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
271 ; CHECK-NEXT: [[C:%.*]] = fadd float [[B]], 1.000000e+00
272 ; CHECK-NEXT: [[TMP8:%.*]] = fadd double [[TMP7]], 1.000000e+00
273 ; CHECK-NEXT: [[TMP9:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_store(ptr [[A]], i64 1)
274 ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[A]] to i64
275 ; CHECK-NEXT: [[TMP11:%.*]] = call i32 @__nsan_internal_check_float_d(float [[C]], double [[TMP8]], i32 4, i64 [[TMP10]])
276 ; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 1
277 ; CHECK-NEXT: [[TMP13:%.*]] = fpext float [[C]] to double
278 ; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP12]], double [[TMP13]], double [[TMP8]]
279 ; CHECK-NEXT: store double [[TMP14]], ptr [[TMP9]], align 1
280 ; CHECK-NEXT: store float [[C]], ptr [[A]], align 1
281 ; CHECK-NEXT: ret void
284 %b = load float, ptr %a, align 1
285 %c = fadd float %b, 1.0
286 store float %c, ptr %a, align 1
290 define void @load_add_store_x86_fp80(ptr %a) sanitize_numerical_stability {
291 ; CHECK-LABEL: @load_add_store_x86_fp80(
293 ; CHECK-NEXT: [[B:%.*]] = load x86_fp80, ptr [[A:%.*]], align 1
294 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_longdouble_load(ptr [[A]], i64 1)
295 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
296 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
298 ; CHECK-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP0]], align 1
299 ; CHECK-NEXT: br label [[TMP6:%.*]]
301 ; CHECK-NEXT: [[TMP5:%.*]] = fpext x86_fp80 [[B]] to fp128
302 ; CHECK-NEXT: br label [[TMP6]]
304 ; CHECK-NEXT: [[TMP7:%.*]] = phi fp128 [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
305 ; CHECK-NEXT: [[C:%.*]] = fadd x86_fp80 [[B]], 0xK3FC9E69594BEC44DE000
306 ; CHECK-NEXT: [[TMP8:%.*]] = fadd fp128 [[TMP7]], 0xLC0000000000000003FC9CD2B297D889B
307 ; CHECK-NEXT: [[TMP9:%.*]] = call ptr @__nsan_get_shadow_ptr_for_longdouble_store(ptr [[A]], i64 1)
308 ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[A]] to i64
309 ; CHECK-NEXT: [[TMP11:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[C]], fp128 [[TMP8]], i32 4, i64 [[TMP10]])
310 ; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 1
311 ; CHECK-NEXT: [[TMP13:%.*]] = fpext x86_fp80 [[C]] to fp128
312 ; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP12]], fp128 [[TMP13]], fp128 [[TMP8]]
313 ; CHECK-NEXT: store fp128 [[TMP14]], ptr [[TMP9]], align 1
314 ; CHECK-NEXT: store x86_fp80 [[C]], ptr [[A]], align 1
315 ; CHECK-NEXT: ret void
318 %b = load x86_fp80, ptr %a, align 1
319 %c = fadd x86_fp80 %b, 0xK3FC9E69594BEC44DE000
320 store x86_fp80 %c, ptr %a, align 1
324 define void @load_add_store_double(ptr %a) sanitize_numerical_stability {
325 ; DQQ-LABEL: @load_add_store_double(
327 ; DQQ-NEXT: [[B:%.*]] = load double, ptr [[A:%.*]], align 1
328 ; DQQ-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_load(ptr [[A]], i64 1)
329 ; DQQ-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
330 ; DQQ-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
332 ; DQQ-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP0]], align 1
333 ; DQQ-NEXT: br label [[TMP6:%.*]]
335 ; DQQ-NEXT: [[TMP5:%.*]] = fpext double [[B]] to fp128
336 ; DQQ-NEXT: br label [[TMP6]]
338 ; DQQ-NEXT: [[TMP7:%.*]] = phi fp128 [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
339 ; DQQ-NEXT: [[C:%.*]] = fadd double [[B]], 1.000000e+00
340 ; DQQ-NEXT: [[TMP8:%.*]] = fadd fp128 [[TMP7]], 0xL00000000000000003FFF000000000000
341 ; DQQ-NEXT: [[TMP9:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_store(ptr [[A]], i64 1)
342 ; DQQ-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[A]] to i64
343 ; DQQ-NEXT: [[TMP11:%.*]] = call i32 @__nsan_internal_check_double_q(double [[C]], fp128 [[TMP8]], i32 4, i64 [[TMP10]])
344 ; DQQ-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 1
345 ; DQQ-NEXT: [[TMP13:%.*]] = fpext double [[C]] to fp128
346 ; DQQ-NEXT: [[TMP14:%.*]] = select i1 [[TMP12]], fp128 [[TMP13]], fp128 [[TMP8]]
347 ; DQQ-NEXT: store fp128 [[TMP14]], ptr [[TMP9]], align 1
348 ; DQQ-NEXT: store double [[C]], ptr [[A]], align 1
351 ; DLQ-LABEL: @load_add_store_double(
353 ; DLQ-NEXT: [[B:%.*]] = load double, ptr [[A:%.*]], align 1
354 ; DLQ-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_load(ptr [[A]], i64 1)
355 ; DLQ-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
356 ; DLQ-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
358 ; DLQ-NEXT: [[TMP3:%.*]] = load x86_fp80, ptr [[TMP0]], align 1
359 ; DLQ-NEXT: br label [[TMP6:%.*]]
361 ; DLQ-NEXT: [[TMP5:%.*]] = fpext double [[B]] to x86_fp80
362 ; DLQ-NEXT: br label [[TMP6]]
364 ; DLQ-NEXT: [[TMP7:%.*]] = phi x86_fp80 [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
365 ; DLQ-NEXT: [[C:%.*]] = fadd double [[B]], 1.000000e+00
366 ; DLQ-NEXT: [[TMP8:%.*]] = fadd x86_fp80 [[TMP7]], 0xK3FFF8000000000000000
367 ; DLQ-NEXT: [[TMP9:%.*]] = call ptr @__nsan_get_shadow_ptr_for_double_store(ptr [[A]], i64 1)
368 ; DLQ-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[A]] to i64
369 ; DLQ-NEXT: [[TMP11:%.*]] = call i32 @__nsan_internal_check_double_l(double [[C]], x86_fp80 [[TMP8]], i32 4, i64 [[TMP10]])
370 ; DLQ-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 1
371 ; DLQ-NEXT: [[TMP13:%.*]] = fpext double [[C]] to x86_fp80
372 ; DLQ-NEXT: [[TMP14:%.*]] = select i1 [[TMP12]], x86_fp80 [[TMP13]], x86_fp80 [[TMP8]]
373 ; DLQ-NEXT: store x86_fp80 [[TMP14]], ptr [[TMP9]], align 1
374 ; DLQ-NEXT: store double [[C]], ptr [[A]], align 1
378 %b = load double, ptr %a, align 1
379 %c = fadd double %b, 1.0
380 store double %c, ptr %a, align 1
384 define void @load_add_store_vector(<2 x float>* %a) sanitize_numerical_stability {
385 ; CHECK-LABEL: @load_add_store_vector(
387 ; CHECK-NEXT: [[B:%.*]] = load <2 x float>, ptr [[A:%.*]], align 1
388 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_load(ptr [[A]], i64 2)
389 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
390 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
392 ; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr [[TMP0]], align 1
393 ; CHECK-NEXT: br label [[TMP6:%.*]]
395 ; CHECK-NEXT: [[TMP5:%.*]] = fpext <2 x float> [[B]] to <2 x double>
396 ; CHECK-NEXT: br label [[TMP6]]
398 ; CHECK-NEXT: [[TMP7:%.*]] = phi <2 x double> [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
399 ; CHECK-NEXT: [[C:%.*]] = fadd <2 x float> [[B]], splat (float 1.000000e+00)
400 ; CHECK-NEXT: [[TMP8:%.*]] = fadd <2 x double> [[TMP7]], splat (double 1.000000e+00)
401 ; CHECK-NEXT: [[TMP9:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_store(ptr [[A]], i64 2)
402 ; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x float> [[C]], i64 0
403 ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x double> [[TMP8]], i64 0
404 ; CHECK-NEXT: [[TMP12:%.*]] = ptrtoint ptr [[A]] to i64
405 ; CHECK-NEXT: [[TMP13:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP10]], double [[TMP11]], i32 4, i64 [[TMP12]])
406 ; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[C]], i64 1
407 ; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x double> [[TMP8]], i64 1
408 ; CHECK-NEXT: [[TMP16:%.*]] = ptrtoint ptr [[A]] to i64
409 ; CHECK-NEXT: [[TMP17:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP14]], double [[TMP15]], i32 4, i64 [[TMP16]])
410 ; CHECK-NEXT: [[TMP18:%.*]] = or i32 [[TMP13]], [[TMP17]]
411 ; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i32 [[TMP18]], 1
412 ; CHECK-NEXT: [[TMP20:%.*]] = fpext <2 x float> [[C]] to <2 x double>
413 ; CHECK-NEXT: [[TMP21:%.*]] = select i1 [[TMP19]], <2 x double> [[TMP20]], <2 x double> [[TMP8]]
414 ; CHECK-NEXT: store <2 x double> [[TMP21]], ptr [[TMP9]], align 1
415 ; CHECK-NEXT: store <2 x float> [[C]], ptr [[A]], align 1
416 ; CHECK-NEXT: ret void
419 %b = load <2 x float>, ptr %a, align 1
420 %c = fadd <2 x float> %b, <float 1.0, float 1.0>
421 store <2 x float> %c, ptr %a, align 1
425 declare float @returns_float()
427 define void @call_fn_returning_float(ptr %dst) sanitize_numerical_stability {
428 ; CHECK-LABEL: @call_fn_returning_float(
430 ; CHECK-NEXT: [[B:%.*]] = call float @returns_float()
431 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_ret_tag, align 8
432 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @returns_float to i64)
433 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_ret_ptr, align 8
434 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[B]] to double
435 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
436 ; CHECK-NEXT: [[C:%.*]] = fadd float [[B]], 1.000000e+00
437 ; CHECK-NEXT: [[TMP5:%.*]] = fadd double [[TMP4]], 1.000000e+00
438 ; CHECK-NEXT: [[TMP6:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_store(ptr [[DST:%.*]], i64 1)
439 ; CHECK-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[DST]] to i64
440 ; CHECK-NEXT: [[TMP8:%.*]] = call i32 @__nsan_internal_check_float_d(float [[C]], double [[TMP5]], i32 4, i64 [[TMP7]])
441 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 1
442 ; CHECK-NEXT: [[TMP10:%.*]] = fpext float [[C]] to double
443 ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP9]], double [[TMP10]], double [[TMP5]]
444 ; CHECK-NEXT: store double [[TMP11]], ptr [[TMP6]], align 1
445 ; CHECK-NEXT: store float [[C]], ptr [[DST]], align 1
446 ; CHECK-NEXT: ret void
449 %b = call float @returns_float()
450 %c = fadd float %b, 1.0
451 store float %c, ptr %dst, align 1
455 define float @return_fn_returning_float(ptr %dst) sanitize_numerical_stability {
456 ; CHECK-LABEL: @return_fn_returning_float(
458 ; CHECK-NEXT: [[B:%.*]] = call float @returns_float()
459 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_ret_tag, align 8
460 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @returns_float to i64)
461 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_ret_ptr, align 8
462 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[B]] to double
463 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
464 ; CHECK-NEXT: [[TMP5:%.*]] = call i32 @__nsan_internal_check_float_d(float [[B]], double [[TMP4]], i32 1, i64 0)
465 ; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 1
466 ; CHECK-NEXT: [[TMP7:%.*]] = fpext float [[B]] to double
467 ; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP6]], double [[TMP7]], double [[TMP4]]
468 ; CHECK-NEXT: store i64 ptrtoint (ptr @return_fn_returning_float to i64), ptr @__nsan_shadow_ret_tag, align 8
469 ; CHECK-NEXT: store double [[TMP8]], ptr @__nsan_shadow_ret_ptr, align 8
470 ; CHECK-NEXT: ret float [[B]]
473 %b = call float @returns_float()
477 declare void @takes_floats(float %a, i8 %b, double %c, x86_fp80 %d)
479 define void @call_fn_taking_float() sanitize_numerical_stability {
480 ; DQQ-LABEL: @call_fn_taking_float(
482 ; DQQ-NEXT: store ptr @takes_floats, ptr @__nsan_shadow_args_tag, align 8
483 ; DQQ-NEXT: store double 1.000000e+00, ptr @__nsan_shadow_args_ptr, align 1
484 ; DQQ-NEXT: store fp128 0xL00000000000000004000800000000000, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 8), align 1
485 ; DQQ-NEXT: store fp128 0xLC0000000000000003FC9CD2B297D889B, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 24), align 1
486 ; DQQ-NEXT: call void @takes_floats(float 1.000000e+00, i8 2, double 3.000000e+00, x86_fp80 0xK3FC9E69594BEC44DE000)
489 ; DLQ-LABEL: @call_fn_taking_float(
491 ; DLQ-NEXT: store ptr @takes_floats, ptr @__nsan_shadow_args_tag, align 8
492 ; DLQ-NEXT: store double 1.000000e+00, ptr @__nsan_shadow_args_ptr, align 1
493 ; DLQ-NEXT: store x86_fp80 0xK4000C000000000000000, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 8), align 1
494 ; DLQ-NEXT: store fp128 0xLC0000000000000003FC9CD2B297D889B, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 18), align 1
495 ; DLQ-NEXT: call void @takes_floats(float 1.000000e+00, i8 2, double 3.000000e+00, x86_fp80 0xK3FC9E69594BEC44DE000)
499 call void @takes_floats(float 1.0, i8 2, double 3.0, x86_fp80 0xK3FC9E69594BEC44DE000)
503 declare float @llvm.sin.f32(float) readnone
505 define float @call_sin_intrinsic() sanitize_numerical_stability {
506 ; CHECK-LABEL: @call_sin_intrinsic(
508 ; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float 1.000000e+00)
509 ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.sin.f64(double 1.000000e+00)
510 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0)
511 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
512 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double
513 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]]
514 ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sin_intrinsic to i64), ptr @__nsan_shadow_ret_tag, align 8
515 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8
516 ; CHECK-NEXT: ret float [[R]]
519 %r = call float @llvm.sin.f32(float 1.0)
523 declare float @sinf(float)
525 define float @call_sinf_libfunc() sanitize_numerical_stability {
526 ; CHECK-LABEL: @call_sinf_libfunc(
528 ; CHECK-NEXT: [[R:%.*]] = call float @sinf(float 1.000000e+00) #[[ATTR4:[0-9]+]]
529 ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.sin.f64(double 1.000000e+00)
530 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0)
531 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
532 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double
533 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]]
534 ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sinf_libfunc to i64), ptr @__nsan_shadow_ret_tag, align 8
535 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8
536 ; CHECK-NEXT: ret float [[R]]
539 %r = call float @sinf(float 1.0)
543 declare double @sin(double)
545 ; FIXME: nsan uses `sin(double)` for fp128.
546 define double @call_sin_libfunc() sanitize_numerical_stability {
547 ; DQQ-LABEL: @call_sin_libfunc(
549 ; DQQ-NEXT: [[R:%.*]] = call double @sin(double 1.000000e+00) #[[ATTR4]]
550 ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000)
551 ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
552 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0)
553 ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
554 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128
555 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
556 ; DQQ-NEXT: store i64 ptrtoint (ptr @call_sin_libfunc to i64), ptr @__nsan_shadow_ret_tag, align 8
557 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
558 ; DQQ-NEXT: ret double [[R]]
560 ; DLQ-LABEL: @call_sin_libfunc(
562 ; DLQ-NEXT: [[R:%.*]] = call double @sin(double 1.000000e+00) #[[ATTR4]]
563 ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000)
564 ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0)
565 ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
566 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80
567 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]]
568 ; DLQ-NEXT: store i64 ptrtoint (ptr @call_sin_libfunc to i64), ptr @__nsan_shadow_ret_tag, align 8
569 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16
570 ; DLQ-NEXT: ret double [[R]]
573 %r = call double @sin(double 1.0)
577 declare double @frexp(double, i32*)
579 define double @call_frexp_libfunc_nointrinsic(double %0, i32* nocapture %1) sanitize_numerical_stability {
580 ; DQQ-LABEL: @call_frexp_libfunc_nointrinsic(
581 ; DQQ-NEXT: [[TMP3:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
582 ; DQQ-NEXT: [[TMP4:%.*]] = icmp eq i64 [[TMP3]], ptrtoint (ptr @call_frexp_libfunc_nointrinsic to i64)
583 ; DQQ-NEXT: [[TMP5:%.*]] = load fp128, ptr @__nsan_shadow_args_ptr, align 1
584 ; DQQ-NEXT: [[TMP6:%.*]] = fpext double [[TMP0:%.*]] to fp128
585 ; DQQ-NEXT: [[TMP7:%.*]] = select i1 [[TMP4]], fp128 [[TMP5]], fp128 [[TMP6]]
586 ; DQQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
587 ; DQQ-NEXT: [[TMP8:%.*]] = call i32 @__nsan_internal_check_double_q(double [[TMP0]], fp128 [[TMP7]], i32 2, i64 0)
588 ; DQQ-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 1
589 ; DQQ-NEXT: [[TMP10:%.*]] = fpext double [[TMP0]] to fp128
590 ; DQQ-NEXT: [[TMP11:%.*]] = select i1 [[TMP9]], fp128 [[TMP10]], fp128 [[TMP7]]
591 ; DQQ-NEXT: [[TMP12:%.*]] = tail call double @frexp(double [[TMP0]], ptr [[TMP1:%.*]])
592 ; DQQ-NEXT: [[TMP13:%.*]] = load i64, ptr @__nsan_shadow_ret_tag, align 8
593 ; DQQ-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], ptrtoint (ptr @frexp to i64)
594 ; DQQ-NEXT: [[TMP15:%.*]] = load fp128, ptr @__nsan_shadow_ret_ptr, align 16
595 ; DQQ-NEXT: [[TMP16:%.*]] = fpext double [[TMP12]] to fp128
596 ; DQQ-NEXT: [[TMP17:%.*]] = select i1 [[TMP14]], fp128 [[TMP15]], fp128 [[TMP16]]
597 ; DQQ-NEXT: [[TMP18:%.*]] = call i32 @__nsan_internal_check_double_q(double [[TMP12]], fp128 [[TMP17]], i32 1, i64 0)
598 ; DQQ-NEXT: [[TMP19:%.*]] = icmp eq i32 [[TMP18]], 1
599 ; DQQ-NEXT: [[TMP20:%.*]] = fpext double [[TMP12]] to fp128
600 ; DQQ-NEXT: [[TMP21:%.*]] = select i1 [[TMP19]], fp128 [[TMP20]], fp128 [[TMP17]]
601 ; DQQ-NEXT: store i64 ptrtoint (ptr @call_frexp_libfunc_nointrinsic to i64), ptr @__nsan_shadow_ret_tag, align 8
602 ; DQQ-NEXT: store fp128 [[TMP21]], ptr @__nsan_shadow_ret_ptr, align 16
603 ; DQQ-NEXT: ret double [[TMP12]]
605 ; DLQ-LABEL: @call_frexp_libfunc_nointrinsic(
606 ; DLQ-NEXT: [[TMP3:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
607 ; DLQ-NEXT: [[TMP4:%.*]] = icmp eq i64 [[TMP3]], ptrtoint (ptr @call_frexp_libfunc_nointrinsic to i64)
608 ; DLQ-NEXT: [[TMP5:%.*]] = load x86_fp80, ptr @__nsan_shadow_args_ptr, align 1
609 ; DLQ-NEXT: [[TMP6:%.*]] = fpext double [[TMP0:%.*]] to x86_fp80
610 ; DLQ-NEXT: [[TMP7:%.*]] = select i1 [[TMP4]], x86_fp80 [[TMP5]], x86_fp80 [[TMP6]]
611 ; DLQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
612 ; DLQ-NEXT: [[TMP8:%.*]] = call i32 @__nsan_internal_check_double_l(double [[TMP0]], x86_fp80 [[TMP7]], i32 2, i64 0)
613 ; DLQ-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 1
614 ; DLQ-NEXT: [[TMP10:%.*]] = fpext double [[TMP0]] to x86_fp80
615 ; DLQ-NEXT: [[TMP11:%.*]] = select i1 [[TMP9]], x86_fp80 [[TMP10]], x86_fp80 [[TMP7]]
616 ; DLQ-NEXT: [[TMP12:%.*]] = tail call double @frexp(double [[TMP0]], ptr [[TMP1:%.*]])
617 ; DLQ-NEXT: [[TMP13:%.*]] = load i64, ptr @__nsan_shadow_ret_tag, align 8
618 ; DLQ-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], ptrtoint (ptr @frexp to i64)
619 ; DLQ-NEXT: [[TMP15:%.*]] = load x86_fp80, ptr @__nsan_shadow_ret_ptr, align 16
620 ; DLQ-NEXT: [[TMP16:%.*]] = fpext double [[TMP12]] to x86_fp80
621 ; DLQ-NEXT: [[TMP17:%.*]] = select i1 [[TMP14]], x86_fp80 [[TMP15]], x86_fp80 [[TMP16]]
622 ; DLQ-NEXT: [[TMP18:%.*]] = call i32 @__nsan_internal_check_double_l(double [[TMP12]], x86_fp80 [[TMP17]], i32 1, i64 0)
623 ; DLQ-NEXT: [[TMP19:%.*]] = icmp eq i32 [[TMP18]], 1
624 ; DLQ-NEXT: [[TMP20:%.*]] = fpext double [[TMP12]] to x86_fp80
625 ; DLQ-NEXT: [[TMP21:%.*]] = select i1 [[TMP19]], x86_fp80 [[TMP20]], x86_fp80 [[TMP17]]
626 ; DLQ-NEXT: store i64 ptrtoint (ptr @call_frexp_libfunc_nointrinsic to i64), ptr @__nsan_shadow_ret_tag, align 8
627 ; DLQ-NEXT: store x86_fp80 [[TMP21]], ptr @__nsan_shadow_ret_ptr, align 16
628 ; DLQ-NEXT: ret double [[TMP12]]
630 %3 = tail call double @frexp(double %0, i32* %1)
634 define float @call_fn_taking_float_by_fn_ptr(float (float)* nocapture %fn_ptr) sanitize_numerical_stability {
635 ; CHECK-LABEL: @call_fn_taking_float_by_fn_ptr(
637 ; CHECK-NEXT: store ptr [[FN_PTR:%.*]], ptr @__nsan_shadow_args_tag, align 8
638 ; CHECK-NEXT: store double 1.000000e+00, ptr @__nsan_shadow_args_ptr, align 1
639 ; CHECK-NEXT: [[R:%.*]] = call float [[FN_PTR]](float 1.000000e+00)
640 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_ret_tag, align 8
641 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[FN_PTR]] to i64
642 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP0]], [[TMP1]]
643 ; CHECK-NEXT: [[TMP3:%.*]] = load double, ptr @__nsan_shadow_ret_ptr, align 8
644 ; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[R]] to double
645 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP4]]
646 ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP5]], i32 1, i64 0)
647 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
648 ; CHECK-NEXT: [[TMP8:%.*]] = fpext float [[R]] to double
649 ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], double [[TMP8]], double [[TMP5]]
650 ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fn_taking_float_by_fn_ptr to i64), ptr @__nsan_shadow_ret_tag, align 8
651 ; CHECK-NEXT: store double [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 8
652 ; CHECK-NEXT: ret float [[R]]
655 %r = call float %fn_ptr(float 1.0)
659 define void @store_float(ptr %dst) sanitize_numerical_stability {
660 ; CHECK-LABEL: @store_float(
662 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__nsan_get_shadow_ptr_for_float_store(ptr [[DST:%.*]], i64 1)
663 ; CHECK-NEXT: store double 4.200000e+01, ptr [[TMP0]], align 1
664 ; CHECK-NEXT: store float 4.200000e+01, ptr [[DST]], align 1
665 ; CHECK-NEXT: ret void
668 store float 42.0, ptr %dst, align 1
672 define i1 @inline_asm(double %0) sanitize_numerical_stability {
673 ; DQQ-LABEL: @inline_asm(
675 ; DQQ-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
676 ; DQQ-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @inline_asm to i64)
677 ; DQQ-NEXT: [[TMP3:%.*]] = load fp128, ptr @__nsan_shadow_args_ptr, align 1
678 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0:%.*]] to fp128
679 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], fp128 [[TMP3]], fp128 [[TMP4]]
680 ; DQQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
681 ; DQQ-NEXT: [[TMP6:%.*]] = call i32 asm "pmovmskb $1, $0", "=r,x,~{dirflag},~{fpsr},~{flags}"(double [[TMP0]])
682 ; DQQ-NEXT: [[TMP7:%.*]] = trunc i32 [[TMP6]] to i8
683 ; DQQ-NEXT: [[TMP8:%.*]] = icmp slt i8 [[TMP7]], 0
684 ; DQQ-NEXT: ret i1 [[TMP8]]
686 ; DLQ-LABEL: @inline_asm(
688 ; DLQ-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
689 ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @inline_asm to i64)
690 ; DLQ-NEXT: [[TMP3:%.*]] = load x86_fp80, ptr @__nsan_shadow_args_ptr, align 1
691 ; DLQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0:%.*]] to x86_fp80
692 ; DLQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP4]]
693 ; DLQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
694 ; DLQ-NEXT: [[TMP6:%.*]] = call i32 asm "pmovmskb $1, $0", "=r,x,~{dirflag},~{fpsr},~{flags}"(double [[TMP0]])
695 ; DLQ-NEXT: [[TMP7:%.*]] = trunc i32 [[TMP6]] to i8
696 ; DLQ-NEXT: [[TMP8:%.*]] = icmp slt i8 [[TMP7]], 0
697 ; DLQ-NEXT: ret i1 [[TMP8]]
700 %1 = call i32 asm "pmovmskb $1, $0", "=r,x,~{dirflag},~{fpsr},~{flags}"(double %0)
701 %2 = trunc i32 %1 to i8
702 %3 = icmp slt i8 %2, 0
706 define void @vector_extract(<2 x float> %0) sanitize_numerical_stability {
707 ; CHECK-LABEL: @vector_extract(
709 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
710 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @vector_extract to i64)
711 ; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr @__nsan_shadow_args_ptr, align 1
712 ; CHECK-NEXT: [[TMP4:%.*]] = fpext <2 x float> [[TMP0:%.*]] to <2 x double>
713 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], <2 x double> [[TMP3]], <2 x double> [[TMP4]]
714 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
715 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[TMP0]], i32 1
716 ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[TMP5]], i32 1
717 ; CHECK-NEXT: ret void
720 %1 = extractelement <2 x float> %0, i32 1
724 define void @vector_insert(<2 x float> %0) sanitize_numerical_stability {
725 ; CHECK-LABEL: @vector_insert(
727 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
728 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @vector_insert to i64)
729 ; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr @__nsan_shadow_args_ptr, align 1
730 ; CHECK-NEXT: [[TMP4:%.*]] = fpext <2 x float> [[TMP0:%.*]] to <2 x double>
731 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], <2 x double> [[TMP3]], <2 x double> [[TMP4]]
732 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
733 ; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x float> [[TMP0]], float 1.000000e+00, i32 1
734 ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[TMP5]], double 1.000000e+00, i32 1
735 ; CHECK-NEXT: ret void
738 %1 = insertelement <2 x float> %0, float 1.0, i32 1
742 define void @freeze_vector_insert(<2 x float> %vec, i32 %idx, float %scalar) sanitize_numerical_stability {
743 ; CHECK-LABEL: @freeze_vector_insert(
745 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
746 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @freeze_vector_insert to i64)
747 ; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr @__nsan_shadow_args_ptr, align 1
748 ; CHECK-NEXT: [[TMP3:%.*]] = fpext <2 x float> [[VEC:%.*]] to <2 x double>
749 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], <2 x double> [[TMP2]], <2 x double> [[TMP3]]
750 ; CHECK-NEXT: [[TMP5:%.*]] = load double, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 16), align 1
751 ; CHECK-NEXT: [[TMP6:%.*]] = fpext float [[SCALAR:%.*]] to double
752 ; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP1]], double [[TMP5]], double [[TMP6]]
753 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
754 ; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x float> [[VEC]], float [[SCALAR]], i32 [[IDX:%.*]]
755 ; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x double> [[TMP4]], double [[TMP7]], i32 [[IDX]]
756 ; CHECK-NEXT: [[FROZEN:%.*]] = freeze <2 x float> [[TMP8]]
757 ; CHECK-NEXT: [[TMP10:%.*]] = freeze <2 x double> [[TMP9]]
758 ; CHECK-NEXT: ret void
761 %1 = insertelement <2 x float> %vec, float %scalar, i32 %idx
762 %frozen = freeze <2 x float> %1
766 define void @vector_shuffle(<2 x float> %0) sanitize_numerical_stability {
767 ; CHECK-LABEL: @vector_shuffle(
769 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
770 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @vector_shuffle to i64)
771 ; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr @__nsan_shadow_args_ptr, align 1
772 ; CHECK-NEXT: [[TMP4:%.*]] = fpext <2 x float> [[TMP0:%.*]] to <2 x double>
773 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], <2 x double> [[TMP3]], <2 x double> [[TMP4]]
774 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
775 ; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x float> [[TMP0]], <2 x float> splat (float 1.000000e+00), <2 x i32> <i32 1, i32 3>
776 ; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> [[TMP5]], <2 x double> splat (double 1.000000e+00), <2 x i32> <i32 1, i32 3>
777 ; CHECK-NEXT: ret void
780 %1 = shufflevector <2 x float> %0, <2 x float> <float 1.0, float 1.0>, <2 x i32> <i32 1, i32 3>
784 define void @aggregate_extract({i32, {float, i1}} %0) sanitize_numerical_stability {
785 ; CHECK-LABEL: @aggregate_extract(
787 ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, { float, i1 } } [[TMP0:%.*]], 1, 0
788 ; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double
789 ; CHECK-NEXT: ret void
792 %1 = extractvalue {i32, {float, i1}} %0, 1, 0
796 define void @aggregate_insert({i32, {float, i1}} %0, float %1) sanitize_numerical_stability {
797 ; CHECK-LABEL: @aggregate_insert(
799 ; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
800 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], ptrtoint (ptr @aggregate_insert to i64)
801 ; CHECK-NEXT: [[TMP4:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
802 ; CHECK-NEXT: [[TMP5:%.*]] = fpext float [[TMP1:%.*]] to double
803 ; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], double [[TMP4]], double [[TMP5]]
804 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
805 ; CHECK-NEXT: [[TMP7:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP1]], double [[TMP6]], i32 5, i64 0)
806 ; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 1
807 ; CHECK-NEXT: [[TMP9:%.*]] = fpext float [[TMP1]] to double
808 ; CHECK-NEXT: [[TMP10:%.*]] = select i1 [[TMP8]], double [[TMP9]], double [[TMP6]]
809 ; CHECK-NEXT: [[TMP11:%.*]] = insertvalue { i32, { float, i1 } } [[TMP0:%.*]], float [[TMP1]], 1, 0
810 ; CHECK-NEXT: ret void
813 %2 = insertvalue {i32, {float, i1}} %0, float %1, 1, 0
817 define void @aggregate_insert_avoid_const_check({i32, {float, i1}} %0) sanitize_numerical_stability {
818 ; CHECK-LABEL: @aggregate_insert_avoid_const_check(
820 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, { float, i1 } } [[TMP0:%.*]], float 1.000000e+00, 1, 0
821 ; CHECK-NEXT: ret void
824 %1 = insertvalue {i32, {float, i1}} %0, float 1.0, 1, 0
829 declare float @fabsf(float)
831 define float @sub_fabs(float %a, float %b) sanitize_numerical_stability {
832 ; CHECK-LABEL: @sub_fabs(
834 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
835 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @sub_fabs to i64)
836 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
837 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[A:%.*]] to double
838 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
839 ; CHECK-NEXT: [[TMP5:%.*]] = load double, ptr getelementptr ([16384 x i8], ptr @__nsan_shadow_args_ptr, i64 0, i64 8), align 1
840 ; CHECK-NEXT: [[TMP6:%.*]] = fpext float [[B:%.*]] to double
841 ; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP1]], double [[TMP5]], double [[TMP6]]
842 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
843 ; CHECK-NEXT: [[S:%.*]] = fsub float [[A]], [[B]]
844 ; CHECK-NEXT: [[TMP8:%.*]] = fsub double [[TMP4]], [[TMP7]]
845 ; CHECK-NEXT: [[TMP9:%.*]] = call i32 @__nsan_internal_check_float_d(float [[S]], double [[TMP8]], i32 2, i64 0)
846 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 1
847 ; CHECK-NEXT: [[TMP11:%.*]] = fpext float [[S]] to double
848 ; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP10]], double [[TMP11]], double [[TMP8]]
849 ; CHECK-NEXT: [[R:%.*]] = call float @fabsf(float [[S]]) #[[ATTR4]]
850 ; CHECK-NEXT: [[TMP13:%.*]] = call double @llvm.fabs.f64(double [[TMP8]])
851 ; CHECK-NEXT: [[TMP14:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP13]], i32 1, i64 0)
852 ; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i32 [[TMP14]], 1
853 ; CHECK-NEXT: [[TMP16:%.*]] = fpext float [[R]] to double
854 ; CHECK-NEXT: [[TMP17:%.*]] = select i1 [[TMP15]], double [[TMP16]], double [[TMP13]]
855 ; CHECK-NEXT: store i64 ptrtoint (ptr @sub_fabs to i64), ptr @__nsan_shadow_ret_tag, align 8
856 ; CHECK-NEXT: store double [[TMP17]], ptr @__nsan_shadow_ret_ptr, align 8
857 ; CHECK-NEXT: ret float [[R]]
860 %s = fsub float %a, %b
861 %r = call float @fabsf(float %s)
865 ; Note that the `unsafe-fp-math` from the function attributes should be moved to
866 ; individual instructions, with the shadow instructions NOT getting the attribute.
867 define float @param_add_return_float_unsafe_fp_math(float %a) #0 {
868 ; CHECK-LABEL: @param_add_return_float_unsafe_fp_math(
870 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
871 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @param_add_return_float_unsafe_fp_math to i64)
872 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
873 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[A:%.*]] to double
874 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
875 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
876 ; CHECK-NEXT: [[B:%.*]] = fadd fast float [[A]], 1.000000e+00
877 ; CHECK-NEXT: [[TMP5:%.*]] = fadd double [[TMP4]], 1.000000e+00
878 ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @__nsan_internal_check_float_d(float [[B]], double [[TMP5]], i32 1, i64 0)
879 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 1
880 ; CHECK-NEXT: [[TMP8:%.*]] = fpext float [[B]] to double
881 ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], double [[TMP8]], double [[TMP5]]
882 ; CHECK-NEXT: store i64 ptrtoint (ptr @param_add_return_float_unsafe_fp_math to i64), ptr @__nsan_shadow_ret_tag, align 8
883 ; CHECK-NEXT: store double [[TMP9]], ptr @__nsan_shadow_ret_ptr, align 8
884 ; CHECK-NEXT: ret float [[B]]
887 %b = fadd float %a, 1.0
892 define void @truncate(<2 x double> %0) sanitize_numerical_stability {
893 ; DQQ-LABEL: @truncate(
895 ; DQQ-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
896 ; DQQ-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @truncate to i64)
897 ; DQQ-NEXT: [[TMP3:%.*]] = load <2 x fp128>, ptr @__nsan_shadow_args_ptr, align 1
898 ; DQQ-NEXT: [[TMP4:%.*]] = fpext <2 x double> [[TMP0:%.*]] to <2 x fp128>
899 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], <2 x fp128> [[TMP3]], <2 x fp128> [[TMP4]]
900 ; DQQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
901 ; DQQ-NEXT: [[TMP6:%.*]] = fptrunc <2 x double> [[TMP0]] to <2 x float>
902 ; DQQ-NEXT: [[TMP7:%.*]] = fptrunc <2 x fp128> [[TMP5]] to <2 x double>
905 ; DLQ-LABEL: @truncate(
907 ; DLQ-NEXT: [[TMP1:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
908 ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], ptrtoint (ptr @truncate to i64)
909 ; DLQ-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr @__nsan_shadow_args_ptr, align 1
910 ; DLQ-NEXT: [[TMP4:%.*]] = fpext <2 x double> [[TMP0:%.*]] to <2 x x86_fp80>
911 ; DLQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], <2 x x86_fp80> [[TMP3]], <2 x x86_fp80> [[TMP4]]
912 ; DLQ-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
913 ; DLQ-NEXT: [[TMP6:%.*]] = fptrunc <2 x double> [[TMP0]] to <2 x float>
914 ; DLQ-NEXT: [[TMP7:%.*]] = fptrunc <2 x x86_fp80> [[TMP5]] to <2 x double>
918 %1 = fptrunc <2 x double> %0 to <2 x float>
922 define void @unaryop(float %a) sanitize_numerical_stability {
923 ; CHECK-LABEL: @unaryop(
925 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__nsan_shadow_args_tag, align 8
926 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], ptrtoint (ptr @unaryop to i64)
927 ; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr @__nsan_shadow_args_ptr, align 1
928 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[A:%.*]] to double
929 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], double [[TMP2]], double [[TMP3]]
930 ; CHECK-NEXT: store i64 0, ptr @__nsan_shadow_args_tag, align 8
931 ; CHECK-NEXT: [[C:%.*]] = fneg float [[A]]
932 ; CHECK-NEXT: [[TMP5:%.*]] = fneg double [[TMP4]]
933 ; CHECK-NEXT: ret void
941 attributes #0 = { nounwind readonly uwtable sanitize_numerical_stability "correctly-rounded-divide-sqrt-fp-math"="false" "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="ieee,ieee" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-jump-tables"="false" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="true" "use-soft-float"="false" }