1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4define float @test(float %x) nounwind { 5; CHECK-LABEL: @test( 6; CHECK-NEXT: [[T34:%.*]] = fadd float [[X:%.*]], 0.000000e+00 7; CHECK-NEXT: ret float [[T34]] 8; 9 %t1 = fpext float %x to double 10 %t3 = fadd double %t1, 0.000000e+00 11 %t34 = fptrunc double %t3 to float 12 ret float %t34 13} 14 15define float @test2(float %x, float %y) nounwind { 16; CHECK-LABEL: @test2( 17; CHECK-NEXT: [[T56:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 18; CHECK-NEXT: ret float [[T56]] 19; 20 %t1 = fpext float %x to double 21 %t23 = fpext float %y to double 22 %t5 = fmul double %t1, %t23 23 %t56 = fptrunc double %t5 to float 24 ret float %t56 25} 26 27define float @test3(float %x, float %y) nounwind { 28; CHECK-LABEL: @test3( 29; CHECK-NEXT: [[T56:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 30; CHECK-NEXT: ret float [[T56]] 31; 32 %t1 = fpext float %x to double 33 %t23 = fpext float %y to double 34 %t5 = fdiv double %t1, %t23 35 %t56 = fptrunc double %t5 to float 36 ret float %t56 37} 38 39define float @test4(float %x) nounwind { 40; CHECK-LABEL: @test4( 41; CHECK-NEXT: [[T34:%.*]] = fneg float [[X:%.*]] 42; CHECK-NEXT: ret float [[T34]] 43; 44 %t1 = fpext float %x to double 45 %t2 = fsub double -0.000000e+00, %t1 46 %t34 = fptrunc double %t2 to float 47 ret float %t34 48} 49 50define float @test4_unary_fneg(float %x) nounwind { 51; CHECK-LABEL: @test4_unary_fneg( 52; CHECK-NEXT: [[T34:%.*]] = fneg float [[X:%.*]] 53; CHECK-NEXT: ret float [[T34]] 54; 55 %t1 = fpext float %x to double 56 %t2 = fneg double %t1 57 %t34 = fptrunc double %t2 to float 58 ret float %t34 59} 60 61; Test with vector splat constant 62define <2 x float> @test5(<2 x float> %x) nounwind { 63; CHECK-LABEL: @test5( 64; CHECK-NEXT: [[T34:%.*]] = fadd <2 x float> [[X:%.*]], zeroinitializer 65; CHECK-NEXT: ret <2 x float> [[T34]] 66; 67 %t1 = fpext <2 x float> %x to <2 x double> 68 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double 0.000000e+00> 69 %t34 = fptrunc <2 x double> %t3 to <2 x float> 70 ret <2 x float> %t34 71} 72 73; Test with a non-splat constant 74define <2 x float> @test6(<2 x float> %x) nounwind { 75; CHECK-LABEL: @test6( 76; CHECK-NEXT: [[T34:%.*]] = fadd <2 x float> [[X:%.*]], <float 0.000000e+00, float -0.000000e+00> 77; CHECK-NEXT: ret <2 x float> [[T34]] 78; 79 %t1 = fpext <2 x float> %x to <2 x double> 80 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double -0.000000e+00> 81 %t34 = fptrunc <2 x double> %t3 to <2 x float> 82 ret <2 x float> %t34 83} 84 85; Test with an undef element 86; TODO: Support undef elements. 87define <2 x float> @test6_undef(<2 x float> %x) nounwind { 88; CHECK-LABEL: @test6_undef( 89; CHECK-NEXT: [[T1:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> 90; CHECK-NEXT: [[T3:%.*]] = fadd <2 x double> [[T1]], <double 0.000000e+00, double undef> 91; CHECK-NEXT: [[T34:%.*]] = fptrunc <2 x double> [[T3]] to <2 x float> 92; CHECK-NEXT: ret <2 x float> [[T34]] 93; 94 %t1 = fpext <2 x float> %x to <2 x double> 95 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double undef> 96 %t34 = fptrunc <2 x double> %t3 to <2 x float> 97 ret <2 x float> %t34 98} 99 100define <2 x float> @not_half_shrinkable(<2 x float> %x) { 101; CHECK-LABEL: @not_half_shrinkable( 102; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float 0.000000e+00, float 2.049000e+03> 103; CHECK-NEXT: ret <2 x float> [[R]] 104; 105 %ext = fpext <2 x float> %x to <2 x double> 106 %add = fadd <2 x double> %ext, <double 0.0, double 2049.0> 107 %r = fptrunc <2 x double> %add to <2 x float> 108 ret <2 x float> %r 109} 110 111define half @test7(float %a) nounwind { 112; CHECK-LABEL: @test7( 113; CHECK-NEXT: [[Z:%.*]] = fptrunc float [[A:%.*]] to half 114; CHECK-NEXT: ret half [[Z]] 115; 116 %y = fpext float %a to double 117 %z = fptrunc double %y to half 118 ret half %z 119} 120 121define float @test8(half %a) nounwind { 122; CHECK-LABEL: @test8( 123; CHECK-NEXT: [[Z:%.*]] = fpext half [[A:%.*]] to float 124; CHECK-NEXT: ret float [[Z]] 125; 126 %y = fpext half %a to double 127 %z = fptrunc double %y to float 128 ret float %z 129} 130 131define float @test9(half %x, half %y) nounwind { 132; CHECK-LABEL: @test9( 133; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 134; CHECK-NEXT: [[TMP2:%.*]] = fpext half [[Y:%.*]] to float 135; CHECK-NEXT: [[T56:%.*]] = fmul float [[TMP1]], [[TMP2]] 136; CHECK-NEXT: ret float [[T56]] 137; 138 %t1 = fpext half %x to double 139 %t23 = fpext half %y to double 140 %t5 = fmul double %t1, %t23 141 %t56 = fptrunc double %t5 to float 142 ret float %t56 143} 144 145define float @test10(half %x, float %y) nounwind { 146; CHECK-LABEL: @test10( 147; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 148; CHECK-NEXT: [[T56:%.*]] = fmul float [[TMP1]], [[Y:%.*]] 149; CHECK-NEXT: ret float [[T56]] 150; 151 %t1 = fpext half %x to double 152 %t23 = fpext float %y to double 153 %t5 = fmul double %t1, %t23 154 %t56 = fptrunc double %t5 to float 155 ret float %t56 156} 157 158define float @test11(half %x) nounwind { 159; CHECK-LABEL: @test11( 160; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 161; CHECK-NEXT: [[T34:%.*]] = fadd float [[TMP1]], 0.000000e+00 162; CHECK-NEXT: ret float [[T34]] 163; 164 %t1 = fpext half %x to double 165 %t3 = fadd double %t1, 0.000000e+00 166 %t34 = fptrunc double %t3 to float 167 ret float %t34 168} 169 170define float @test12(float %x, half %y) nounwind { 171; CHECK-LABEL: @test12( 172; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 173; CHECK-NEXT: [[T34:%.*]] = fadd float [[TMP1]], [[X:%.*]] 174; CHECK-NEXT: ret float [[T34]] 175; 176 %t1 = fpext float %x to double 177 %t2 = fpext half %y to double 178 %t3 = fadd double %t1, %t2 179 %t34 = fptrunc double %t3 to float 180 ret float %t34 181} 182 183define float @test13(half %x, float %y) nounwind { 184; CHECK-LABEL: @test13( 185; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 186; CHECK-NEXT: [[T56:%.*]] = fdiv float [[TMP1]], [[Y:%.*]] 187; CHECK-NEXT: ret float [[T56]] 188; 189 %t1 = fpext half %x to double 190 %t23 = fpext float %y to double 191 %t5 = fdiv double %t1, %t23 192 %t56 = fptrunc double %t5 to float 193 ret float %t56 194} 195 196define float @test14(float %x, half %y) nounwind { 197; CHECK-LABEL: @test14( 198; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 199; CHECK-NEXT: [[T56:%.*]] = fdiv float [[X:%.*]], [[TMP1]] 200; CHECK-NEXT: ret float [[T56]] 201; 202 %t1 = fpext float %x to double 203 %t23 = fpext half %y to double 204 %t5 = fdiv double %t1, %t23 205 %t56 = fptrunc double %t5 to float 206 ret float %t56 207} 208 209define float @test15(half %x, half %y) nounwind { 210; CHECK-LABEL: @test15( 211; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 212; CHECK-NEXT: [[TMP2:%.*]] = fpext half [[Y:%.*]] to float 213; CHECK-NEXT: [[T56:%.*]] = fdiv float [[TMP1]], [[TMP2]] 214; CHECK-NEXT: ret float [[T56]] 215; 216 %t1 = fpext half %x to double 217 %t23 = fpext half %y to double 218 %t5 = fdiv double %t1, %t23 219 %t56 = fptrunc double %t5 to float 220 ret float %t56 221} 222 223define float @test16(half %x, float %y) nounwind { 224; CHECK-LABEL: @test16( 225; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 226; CHECK-NEXT: [[TMP2:%.*]] = frem float [[TMP1]], [[Y:%.*]] 227; CHECK-NEXT: ret float [[TMP2]] 228; 229 %t1 = fpext half %x to double 230 %t23 = fpext float %y to double 231 %t5 = frem double %t1, %t23 232 %t56 = fptrunc double %t5 to float 233 ret float %t56 234} 235 236define float @test17(float %x, half %y) nounwind { 237; CHECK-LABEL: @test17( 238; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 239; CHECK-NEXT: [[TMP2:%.*]] = frem float [[X:%.*]], [[TMP1]] 240; CHECK-NEXT: ret float [[TMP2]] 241; 242 %t1 = fpext float %x to double 243 %t23 = fpext half %y to double 244 %t5 = frem double %t1, %t23 245 %t56 = fptrunc double %t5 to float 246 ret float %t56 247} 248 249define float @test18(half %x, half %y) nounwind { 250; CHECK-LABEL: @test18( 251; CHECK-NEXT: [[TMP1:%.*]] = frem half [[X:%.*]], [[Y:%.*]] 252; CHECK-NEXT: [[T56:%.*]] = fpext half [[TMP1]] to float 253; CHECK-NEXT: ret float [[T56]] 254; 255 %t1 = fpext half %x to double 256 %t23 = fpext half %y to double 257 %t5 = frem double %t1, %t23 258 %t56 = fptrunc double %t5 to float 259 ret float %t56 260} 261 262; Convert from integer is exact, so convert directly to double. 263 264define double @ItoFtoF_s25_f32_f64(i25 %i) { 265; CHECK-LABEL: @ItoFtoF_s25_f32_f64( 266; CHECK-NEXT: [[R:%.*]] = sitofp i25 [[I:%.*]] to double 267; CHECK-NEXT: ret double [[R]] 268; 269 %x = sitofp i25 %i to float 270 %r = fpext float %x to double 271 ret double %r 272} 273 274; Convert from integer is exact, so convert directly to fp128. 275 276define fp128 @ItoFtoF_u24_f32_f128(i24 %i) { 277; CHECK-LABEL: @ItoFtoF_u24_f32_f128( 278; CHECK-NEXT: [[R:%.*]] = uitofp i24 [[I:%.*]] to fp128 279; CHECK-NEXT: ret fp128 [[R]] 280; 281 %x = uitofp i24 %i to float 282 %r = fpext float %x to fp128 283 ret fp128 %r 284} 285 286; Negative test - intermediate rounding in float type. 287 288define double @ItoFtoF_s26_f32_f64(i26 %i) { 289; CHECK-LABEL: @ItoFtoF_s26_f32_f64( 290; CHECK-NEXT: [[X:%.*]] = sitofp i26 [[I:%.*]] to float 291; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 292; CHECK-NEXT: ret double [[R]] 293; 294 %x = sitofp i26 %i to float 295 %r = fpext float %x to double 296 ret double %r 297} 298 299; Negative test - intermediate rounding in float type. 300 301define double @ItoFtoF_u25_f32_f64(i25 %i) { 302; CHECK-LABEL: @ItoFtoF_u25_f32_f64( 303; CHECK-NEXT: [[X:%.*]] = uitofp i25 [[I:%.*]] to float 304; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 305; CHECK-NEXT: ret double [[R]] 306; 307 %x = uitofp i25 %i to float 308 %r = fpext float %x to double 309 ret double %r 310} 311 312; UB on overflow guarantees that the input is small enough to fit in i32. 313 314define double @FtoItoFtoF_f32_s32_f32_f64(float %f) { 315; CHECK-LABEL: @FtoItoFtoF_f32_s32_f32_f64( 316; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i32 317; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[I]] to double 318; CHECK-NEXT: ret double [[R]] 319; 320 %i = fptosi float %f to i32 321 %x = sitofp i32 %i to float 322 %r = fpext float %x to double 323 ret double %r 324} 325 326declare void @use_i32(i32) 327declare void @use_f32(float) 328 329; Extra uses are ok; unsigned is ok. 330 331define double @FtoItoFtoF_f32_u32_f32_f64_extra_uses(float %f) { 332; CHECK-LABEL: @FtoItoFtoF_f32_u32_f32_f64_extra_uses( 333; CHECK-NEXT: [[I:%.*]] = fptoui float [[F:%.*]] to i32 334; CHECK-NEXT: call void @use_i32(i32 [[I]]) 335; CHECK-NEXT: [[X:%.*]] = uitofp i32 [[I]] to float 336; CHECK-NEXT: call void @use_f32(float [[X]]) 337; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[I]] to double 338; CHECK-NEXT: ret double [[R]] 339; 340 %i = fptoui float %f to i32 341 call void @use_i32(i32 %i) 342 %x = uitofp i32 %i to float 343 call void @use_f32(float %x) 344 %r = fpext float %x to double 345 ret double %r 346} 347 348; Vectors are ok; initial type can be smaller than intermediate type. 349 350define <3 x double> @FtoItoFtoF_v3f16_v3s32_v3f32_v3f64(<3 x half> %f) { 351; CHECK-LABEL: @FtoItoFtoF_v3f16_v3s32_v3f32_v3f64( 352; CHECK-NEXT: [[I:%.*]] = fptosi <3 x half> [[F:%.*]] to <3 x i32> 353; CHECK-NEXT: [[R:%.*]] = sitofp <3 x i32> [[I]] to <3 x double> 354; CHECK-NEXT: ret <3 x double> [[R]] 355; 356 %i = fptosi <3 x half> %f to <3 x i32> 357 %x = sitofp <3 x i32> %i to <3 x float> 358 %r = fpext <3 x float> %x to <3 x double> 359 ret <3 x double> %r 360} 361 362; Wider than double is ok. 363 364define fp128 @FtoItoFtoF_f32_s64_f64_f128(float %f) { 365; CHECK-LABEL: @FtoItoFtoF_f32_s64_f64_f128( 366; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i64 367; CHECK-NEXT: [[R:%.*]] = sitofp i64 [[I]] to fp128 368; CHECK-NEXT: ret fp128 [[R]] 369; 370 %i = fptosi float %f to i64 371 %x = sitofp i64 %i to double 372 %r = fpext double %x to fp128 373 ret fp128 %r 374} 375 376; Target-specific type is ok. 377 378define x86_fp80 @FtoItoFtoF_f64_u54_f64_f80(double %f) { 379; CHECK-LABEL: @FtoItoFtoF_f64_u54_f64_f80( 380; CHECK-NEXT: [[I:%.*]] = fptoui double [[F:%.*]] to i54 381; CHECK-NEXT: [[R:%.*]] = uitofp i54 [[I]] to x86_fp80 382; CHECK-NEXT: ret x86_fp80 [[R]] 383; 384 %i = fptoui double %f to i54 385 %x = uitofp i54 %i to double 386 %r = fpext double %x to x86_fp80 387 ret x86_fp80 %r 388} 389 390; Weird target-specific type is ok (not possible to extend *from* that type). 391 392define ppc_fp128 @FtoItoFtoF_f64_u54_f64_p128(double %f) { 393; CHECK-LABEL: @FtoItoFtoF_f64_u54_f64_p128( 394; CHECK-NEXT: [[I:%.*]] = fptoui double [[F:%.*]] to i54 395; CHECK-NEXT: [[R:%.*]] = uitofp i54 [[I]] to ppc_fp128 396; CHECK-NEXT: ret ppc_fp128 [[R]] 397; 398 %i = fptoui double %f to i54 399 %x = uitofp i54 %i to double 400 %r = fpext double %x to ppc_fp128 401 ret ppc_fp128 %r 402} 403 404; Unsigned to signed is ok because signed int has smaller magnitude. 405 406define double @FtoItoFtoF_f32_us32_f32_f64(float %f) { 407; CHECK-LABEL: @FtoItoFtoF_f32_us32_f32_f64( 408; CHECK-NEXT: [[I:%.*]] = fptoui float [[F:%.*]] to i32 409; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[I]] to double 410; CHECK-NEXT: ret double [[R]] 411; 412 %i = fptoui float %f to i32 413 %x = sitofp i32 %i to float 414 %r = fpext float %x to double 415 ret double %r 416} 417 418; Negative test: consider -1.0 419 420define double @FtoItoFtoF_f32_su32_f32_f64(float %f) { 421; CHECK-LABEL: @FtoItoFtoF_f32_su32_f32_f64( 422; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i32 423; CHECK-NEXT: [[X:%.*]] = uitofp i32 [[I]] to float 424; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 425; CHECK-NEXT: ret double [[R]] 426; 427 %i = fptosi float %f to i32 428 %x = uitofp i32 %i to float 429 %r = fpext float %x to double 430 ret double %r 431} 432