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 4 5target 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" 6 7declare float @declaration_only(float %a) sanitize_numerical_stability 8 9; Tests with simple control flow. 10 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 14 15 16define float @return_param_float(float %a) sanitize_numerical_stability { 17; CHECK-LABEL: @return_param_float( 18; CHECK-NEXT: entry: 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]] 32; 33entry: 34 ret float %a 35} 36 37; Note that the shadow fadd should not have a `fast` flag. 38define float @param_add_return_float(float %a) sanitize_numerical_stability { 39; CHECK-LABEL: @param_add_return_float( 40; CHECK-NEXT: entry: 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]] 56; 57entry: 58 %b = fadd fast float %a, 1.0 59 ret float %b 60} 61 62define x86_fp80 @param_add_return_x86_fp80(x86_fp80 %a) sanitize_numerical_stability { 63; CHECK-LABEL: @param_add_return_x86_fp80( 64; CHECK-NEXT: entry: 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]] 80; 81entry: 82 %b = fadd x86_fp80 %a, 0xK3FC9E69594BEC44DE000 83 ret x86_fp80 %b 84} 85 86define double @param_add_return_double(double %a) sanitize_numerical_stability { 87; DQQ-LABEL: @param_add_return_double( 88; DQQ-NEXT: entry: 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]] 104; 105; DLQ-LABEL: @param_add_return_double( 106; DLQ-NEXT: entry: 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]] 122; 123entry: 124 %b = fadd double %a, 1.0 125 ret double %b 126} 127 128define <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( 130; CHECK-NEXT: entry: 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]] 152; 153entry: 154 %b = fadd <2 x float> %a, <float 1.0, float 1.0> 155 ret <2 x float> %b 156} 157 158; TODO: This is ignored for now. 159define [2 x float] @return_param_float_array([2 x float] %a) sanitize_numerical_stability { 160; CHECK-LABEL: @return_param_float_array( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: ret [2 x float] [[A:%.*]] 163; 164entry: 165 ret [2 x float] %a 166} 167 168define void @constantload_add_store_float(ptr %dst) sanitize_numerical_stability { 169; CHECK-LABEL: @constantload_add_store_float( 170; CHECK-NEXT: entry: 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 184; 185entry: 186 %b = load float, ptr @float_const 187 %c = fadd float %b, 1.0 188 store float %c, ptr %dst, align 1 189 ret void 190} 191 192define void @constantload_add_store_x86_fp80(ptr %dst) sanitize_numerical_stability { 193; CHECK-LABEL: @constantload_add_store_x86_fp80( 194; CHECK-NEXT: entry: 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 208; 209entry: 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 213 ret void 214} 215 216define void @constantload_add_store_double(ptr %dst) sanitize_numerical_stability { 217; DQQ-LABEL: @constantload_add_store_double( 218; DQQ-NEXT: entry: 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 231; DQQ-NEXT: ret void 232; 233; DLQ-LABEL: @constantload_add_store_double( 234; DLQ-NEXT: entry: 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 247; DLQ-NEXT: ret void 248; 249entry: 250 %b = load double, ptr @double_const 251 %c = fadd double %b, 1.0 252 store double %c, ptr %dst, align 1 253 ret void 254} 255 256define void @load_add_store_float(ptr %a) sanitize_numerical_stability { 257; CHECK-LABEL: @load_add_store_float( 258; CHECK-NEXT: entry: 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:%.*]] 263; CHECK: 2: 264; CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[TMP0]], align 1 265; CHECK-NEXT: br label [[TMP6:%.*]] 266; CHECK: 4: 267; CHECK-NEXT: [[TMP5:%.*]] = fpext float [[B]] to double 268; CHECK-NEXT: br label [[TMP6]] 269; CHECK: 6: 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 282; 283entry: 284 %b = load float, ptr %a, align 1 285 %c = fadd float %b, 1.0 286 store float %c, ptr %a, align 1 287 ret void 288} 289 290define void @load_add_store_x86_fp80(ptr %a) sanitize_numerical_stability { 291; CHECK-LABEL: @load_add_store_x86_fp80( 292; CHECK-NEXT: entry: 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:%.*]] 297; CHECK: 2: 298; CHECK-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP0]], align 1 299; CHECK-NEXT: br label [[TMP6:%.*]] 300; CHECK: 4: 301; CHECK-NEXT: [[TMP5:%.*]] = fpext x86_fp80 [[B]] to fp128 302; CHECK-NEXT: br label [[TMP6]] 303; CHECK: 6: 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 316; 317entry: 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 321 ret void 322} 323 324define void @load_add_store_double(ptr %a) sanitize_numerical_stability { 325; DQQ-LABEL: @load_add_store_double( 326; DQQ-NEXT: entry: 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:%.*]] 331; DQQ: 2: 332; DQQ-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP0]], align 1 333; DQQ-NEXT: br label [[TMP6:%.*]] 334; DQQ: 4: 335; DQQ-NEXT: [[TMP5:%.*]] = fpext double [[B]] to fp128 336; DQQ-NEXT: br label [[TMP6]] 337; DQQ: 6: 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 349; DQQ-NEXT: ret void 350; 351; DLQ-LABEL: @load_add_store_double( 352; DLQ-NEXT: entry: 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:%.*]] 357; DLQ: 2: 358; DLQ-NEXT: [[TMP3:%.*]] = load x86_fp80, ptr [[TMP0]], align 1 359; DLQ-NEXT: br label [[TMP6:%.*]] 360; DLQ: 4: 361; DLQ-NEXT: [[TMP5:%.*]] = fpext double [[B]] to x86_fp80 362; DLQ-NEXT: br label [[TMP6]] 363; DLQ: 6: 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 375; DLQ-NEXT: ret void 376; 377entry: 378 %b = load double, ptr %a, align 1 379 %c = fadd double %b, 1.0 380 store double %c, ptr %a, align 1 381 ret void 382} 383 384define void @load_add_store_vector(<2 x float>* %a) sanitize_numerical_stability { 385; CHECK-LABEL: @load_add_store_vector( 386; CHECK-NEXT: entry: 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:%.*]] 391; CHECK: 2: 392; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr [[TMP0]], align 1 393; CHECK-NEXT: br label [[TMP6:%.*]] 394; CHECK: 4: 395; CHECK-NEXT: [[TMP5:%.*]] = fpext <2 x float> [[B]] to <2 x double> 396; CHECK-NEXT: br label [[TMP6]] 397; CHECK: 6: 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 417; 418entry: 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 422 ret void 423} 424 425declare float @returns_float() 426 427define void @call_fn_returning_float(ptr %dst) sanitize_numerical_stability { 428; CHECK-LABEL: @call_fn_returning_float( 429; CHECK-NEXT: entry: 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 447; 448entry: 449 %b = call float @returns_float() 450 %c = fadd float %b, 1.0 451 store float %c, ptr %dst, align 1 452 ret void 453} 454 455define float @return_fn_returning_float(ptr %dst) sanitize_numerical_stability { 456; CHECK-LABEL: @return_fn_returning_float( 457; CHECK-NEXT: entry: 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]] 471; 472entry: 473 %b = call float @returns_float() 474 ret float %b 475} 476 477declare void @takes_floats(float %a, i8 %b, double %c, x86_fp80 %d) 478 479define void @call_fn_taking_float() sanitize_numerical_stability { 480; DQQ-LABEL: @call_fn_taking_float( 481; DQQ-NEXT: entry: 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) 487; DQQ-NEXT: ret void 488; 489; DLQ-LABEL: @call_fn_taking_float( 490; DLQ-NEXT: entry: 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) 496; DLQ-NEXT: ret void 497; 498entry: 499 call void @takes_floats(float 1.0, i8 2, double 3.0, x86_fp80 0xK3FC9E69594BEC44DE000) 500 ret void 501} 502 503declare float @llvm.sin.f32(float) readnone 504 505define float @call_sin_intrinsic() sanitize_numerical_stability { 506; CHECK-LABEL: @call_sin_intrinsic( 507; CHECK-NEXT: entry: 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]] 517; 518entry: 519 %r = call float @llvm.sin.f32(float 1.0) 520 ret float %r 521} 522 523declare float @sinf(float) 524 525define float @call_sinf_libfunc() sanitize_numerical_stability { 526; CHECK-LABEL: @call_sinf_libfunc( 527; CHECK-NEXT: entry: 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]] 537; 538entry: 539 %r = call float @sinf(float 1.0) 540 ret float %r 541} 542 543declare double @sin(double) 544 545; FIXME: nsan uses `sin(double)` for fp128. 546define double @call_sin_libfunc() sanitize_numerical_stability { 547; DQQ-LABEL: @call_sin_libfunc( 548; DQQ-NEXT: entry: 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]] 559; 560; DLQ-LABEL: @call_sin_libfunc( 561; DLQ-NEXT: entry: 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]] 571; 572entry: 573 %r = call double @sin(double 1.0) 574 ret double %r 575} 576 577declare double @frexp(double, i32*) 578 579define 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]] 604; 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]] 629; 630 %3 = tail call double @frexp(double %0, i32* %1) 631 ret double %3 632} 633 634define 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( 636; CHECK-NEXT: entry: 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]] 653; 654entry: 655 %r = call float %fn_ptr(float 1.0) 656 ret float %r 657} 658 659define void @store_float(ptr %dst) sanitize_numerical_stability { 660; CHECK-LABEL: @store_float( 661; CHECK-NEXT: entry: 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 666; 667entry: 668 store float 42.0, ptr %dst, align 1 669 ret void 670} 671 672define i1 @inline_asm(double %0) sanitize_numerical_stability { 673; DQQ-LABEL: @inline_asm( 674; DQQ-NEXT: entry: 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]] 685; 686; DLQ-LABEL: @inline_asm( 687; DLQ-NEXT: entry: 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]] 698; 699entry: 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 703 ret i1 %3 704} 705 706define void @vector_extract(<2 x float> %0) sanitize_numerical_stability { 707; CHECK-LABEL: @vector_extract( 708; CHECK-NEXT: entry: 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 718; 719entry: 720 %1 = extractelement <2 x float> %0, i32 1 721 ret void 722} 723 724define void @vector_insert(<2 x float> %0) sanitize_numerical_stability { 725; CHECK-LABEL: @vector_insert( 726; CHECK-NEXT: entry: 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 736; 737entry: 738 %1 = insertelement <2 x float> %0, float 1.0, i32 1 739 ret void 740} 741 742define void @freeze_vector_insert(<2 x float> %vec, i32 %idx, float %scalar) sanitize_numerical_stability { 743; CHECK-LABEL: @freeze_vector_insert( 744; CHECK-NEXT: entry: 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 759; 760entry: 761 %1 = insertelement <2 x float> %vec, float %scalar, i32 %idx 762 %frozen = freeze <2 x float> %1 763 ret void 764} 765 766define void @vector_shuffle(<2 x float> %0) sanitize_numerical_stability { 767; CHECK-LABEL: @vector_shuffle( 768; CHECK-NEXT: entry: 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 778; 779entry: 780 %1 = shufflevector <2 x float> %0, <2 x float> <float 1.0, float 1.0>, <2 x i32> <i32 1, i32 3> 781 ret void 782} 783 784define void @aggregate_extract({i32, {float, i1}} %0) sanitize_numerical_stability { 785; CHECK-LABEL: @aggregate_extract( 786; CHECK-NEXT: entry: 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 790; 791entry: 792 %1 = extractvalue {i32, {float, i1}} %0, 1, 0 793 ret void 794} 795 796define void @aggregate_insert({i32, {float, i1}} %0, float %1) sanitize_numerical_stability { 797; CHECK-LABEL: @aggregate_insert( 798; CHECK-NEXT: entry: 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 811; 812entry: 813 %2 = insertvalue {i32, {float, i1}} %0, float %1, 1, 0 814 ret void 815} 816 817define void @aggregate_insert_avoid_const_check({i32, {float, i1}} %0) sanitize_numerical_stability { 818; CHECK-LABEL: @aggregate_insert_avoid_const_check( 819; CHECK-NEXT: entry: 820; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, { float, i1 } } [[TMP0:%.*]], float 1.000000e+00, 1, 0 821; CHECK-NEXT: ret void 822; 823entry: 824 %1 = insertvalue {i32, {float, i1}} %0, float 1.0, 1, 0 825 ret void 826} 827 828 829declare float @fabsf(float) 830 831define float @sub_fabs(float %a, float %b) sanitize_numerical_stability { 832; CHECK-LABEL: @sub_fabs( 833; CHECK-NEXT: entry: 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]] 858; 859entry: 860 %s = fsub float %a, %b 861 %r = call float @fabsf(float %s) 862 ret float %r 863} 864 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. 867define float @param_add_return_float_unsafe_fp_math(float %a) #0 { 868; CHECK-LABEL: @param_add_return_float_unsafe_fp_math( 869; CHECK-NEXT: entry: 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]] 885; 886entry: 887 %b = fadd float %a, 1.0 888 ret float %b 889} 890 891 892define void @truncate(<2 x double> %0) sanitize_numerical_stability { 893; DQQ-LABEL: @truncate( 894; DQQ-NEXT: entry: 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> 903; DQQ-NEXT: ret void 904; 905; DLQ-LABEL: @truncate( 906; DLQ-NEXT: entry: 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> 915; DLQ-NEXT: ret void 916; 917entry: 918 %1 = fptrunc <2 x double> %0 to <2 x float> 919 ret void 920} 921 922define void @unaryop(float %a) sanitize_numerical_stability { 923; CHECK-LABEL: @unaryop( 924; CHECK-NEXT: entry: 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 934; 935entry: 936 %c = fneg float %a 937 ret void 938} 939 940 941attributes #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" } 942