1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i1 @test1(i8 %A) { 5; CHECK-LABEL: @test1( 6; CHECK-NEXT: ret i1 true 7; 8 %B = sitofp i8 %A to double 9 %C = fcmp ult double %B, 128.0 10 ret i1 %C 11} 12 13define i1 @test2(i8 %A) { 14; CHECK-LABEL: @test2( 15; CHECK-NEXT: ret i1 true 16; 17 %B = sitofp i8 %A to double 18 %C = fcmp ugt double %B, -128.1 19 ret i1 %C 20} 21 22define i1 @test3(i8 %A) { 23; CHECK-LABEL: @test3( 24; CHECK-NEXT: ret i1 true 25; 26 %B = sitofp i8 %A to double 27 %C = fcmp ule double %B, 127.0 28 ret i1 %C 29} 30 31define i1 @test4(i8 %A) { 32; CHECK-LABEL: @test4( 33; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[A:%.*]], 127 34; CHECK-NEXT: ret i1 [[C]] 35; 36 %B = sitofp i8 %A to double 37 %C = fcmp ult double %B, 127.0 38 ret i1 %C 39} 40 41define i32 @test5(i32 %A) { 42; CHECK-LABEL: @test5( 43; CHECK-NEXT: ret i32 [[A:%.*]] 44; 45 %B = sitofp i32 %A to double 46 %C = fptosi double %B to i32 47 %D = uitofp i32 %C to double 48 %E = fptoui double %D to i32 49 ret i32 %E 50} 51 52define i32 @test6(i32 %A) { 53; CHECK-LABEL: @test6( 54; CHECK-NEXT: [[ADDCONV:%.*]] = and i32 [[A:%.*]], 39 55; CHECK-NEXT: ret i32 [[ADDCONV]] 56; 57 %B = and i32 %A, 7 58 %C = and i32 %A, 32 59 %D = sitofp i32 %B to double 60 %E = sitofp i32 %C to double 61 %F = fadd double %D, %E 62 %G = fptosi double %F to i32 63 ret i32 %G 64} 65 66define i32 @test7(i32 %A) { 67; CHECK-LABEL: @test7( 68; CHECK-NEXT: ret i32 [[A:%.*]] 69; 70 %B = sitofp i32 %A to double 71 %C = fptoui double %B to i32 72 ret i32 %C 73} 74 75define i32 @test8(i32 %A) { 76; CHECK-LABEL: @test8( 77; CHECK-NEXT: ret i32 [[A:%.*]] 78; 79 %B = uitofp i32 %A to double 80 %C = fptosi double %B to i32 81 ret i32 %C 82} 83 84define i32 @test9(i8 %A) { 85; CHECK-LABEL: @test9( 86; CHECK-NEXT: [[C:%.*]] = zext i8 [[A:%.*]] to i32 87; CHECK-NEXT: ret i32 [[C]] 88; 89 %B = sitofp i8 %A to float 90 %C = fptoui float %B to i32 91 ret i32 %C 92} 93 94define i32 @test10(i8 %A) { 95; CHECK-LABEL: @test10( 96; CHECK-NEXT: [[C:%.*]] = sext i8 [[A:%.*]] to i32 97; CHECK-NEXT: ret i32 [[C]] 98; 99 %B = sitofp i8 %A to float 100 %C = fptosi float %B to i32 101 ret i32 %C 102} 103 104; If the input value is outside of the range of the output cast, it's 105; undefined behavior, so we can assume it fits. 106 107define i8 @test11(i32 %A) { 108; CHECK-LABEL: @test11( 109; CHECK-NEXT: [[C:%.*]] = trunc i32 [[A:%.*]] to i8 110; CHECK-NEXT: ret i8 [[C]] 111; 112 %B = sitofp i32 %A to float 113 %C = fptosi float %B to i8 114 ret i8 %C 115} 116 117; If the input value is negative, it'll be outside the range of the 118; output cast, and thus undefined behavior. 119 120define i32 @test12(i8 %A) { 121; CHECK-LABEL: @test12( 122; CHECK-NEXT: [[C:%.*]] = zext i8 [[A:%.*]] to i32 123; CHECK-NEXT: ret i32 [[C]] 124; 125 %B = sitofp i8 %A to float 126 %C = fptoui float %B to i32 127 ret i32 %C 128} 129 130; This can't fold because the 25-bit input doesn't fit in the mantissa. 131 132define i32 @test13(i25 %A) { 133; CHECK-LABEL: @test13( 134; CHECK-NEXT: [[B:%.*]] = uitofp i25 [[A:%.*]] to float 135; CHECK-NEXT: [[C:%.*]] = fptoui float [[B]] to i32 136; CHECK-NEXT: ret i32 [[C]] 137; 138 %B = uitofp i25 %A to float 139 %C = fptoui float %B to i32 140 ret i32 %C 141} 142 143; But this one can. 144 145define i32 @test14(i24 %A) { 146; CHECK-LABEL: @test14( 147; CHECK-NEXT: [[C:%.*]] = zext i24 [[A:%.*]] to i32 148; CHECK-NEXT: ret i32 [[C]] 149; 150 %B = uitofp i24 %A to float 151 %C = fptoui float %B to i32 152 ret i32 %C 153} 154 155; And this one can too. 156 157define i24 @test15(i32 %A) { 158; CHECK-LABEL: @test15( 159; CHECK-NEXT: [[C:%.*]] = trunc i32 [[A:%.*]] to i24 160; CHECK-NEXT: ret i24 [[C]] 161; 162 %B = uitofp i32 %A to float 163 %C = fptoui float %B to i24 164 ret i24 %C 165} 166 167; This can fold because the 25-bit input is signed and we discard the sign bit. 168 169define i32 @test16(i25 %A) { 170; CHECK-LABEL: @test16( 171; CHECK-NEXT: [[C:%.*]] = zext i25 [[A:%.*]] to i32 172; CHECK-NEXT: ret i32 [[C]] 173; 174 %B = sitofp i25 %A to float 175 %C = fptoui float %B to i32 176 ret i32 %C 177} 178 179; This can't fold because the 26-bit input won't fit the mantissa 180; even after discarding the signed bit. 181 182define i32 @test17(i26 %A) { 183; CHECK-LABEL: @test17( 184; CHECK-NEXT: [[B:%.*]] = sitofp i26 [[A:%.*]] to float 185; CHECK-NEXT: [[C:%.*]] = fptoui float [[B]] to i32 186; CHECK-NEXT: ret i32 [[C]] 187; 188 %B = sitofp i26 %A to float 189 %C = fptoui float %B to i32 190 ret i32 %C 191} 192 193; This can't fold because the 54-bit output is big enough to hold an input 194; that was rounded when converted to double. 195 196define i54 @test18(i64 %A) { 197; CHECK-LABEL: @test18( 198; CHECK-NEXT: [[B:%.*]] = sitofp i64 [[A:%.*]] to double 199; CHECK-NEXT: [[C:%.*]] = fptosi double [[B]] to i54 200; CHECK-NEXT: ret i54 [[C]] 201; 202 %B = sitofp i64 %A to double 203 %C = fptosi double %B to i54 204 ret i54 %C 205} 206 207; This can't fold because the 55-bit output won't fit the mantissa 208; even after discarding the sign bit. 209 210define i55 @test19(i64 %A) { 211; CHECK-LABEL: @test19( 212; CHECK-NEXT: [[B:%.*]] = sitofp i64 [[A:%.*]] to double 213; CHECK-NEXT: [[C:%.*]] = fptosi double [[B]] to i55 214; CHECK-NEXT: ret i55 [[C]] 215; 216 %B = sitofp i64 %A to double 217 %C = fptosi double %B to i55 218 ret i55 %C 219} 220 221; The mask guarantees that the input is small enough to eliminate the FP casts. 222 223define i25 @masked_input(i25 %A) { 224; CHECK-LABEL: @masked_input( 225; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], 65535 226; CHECK-NEXT: ret i25 [[M]] 227; 228 %m = and i25 %A, 65535 229 %B = uitofp i25 %m to float 230 %C = fptoui float %B to i25 231 ret i25 %C 232} 233 234define i25 @max_masked_input(i25 %A) { 235; CHECK-LABEL: @max_masked_input( 236; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], 16777215 237; CHECK-NEXT: ret i25 [[M]] 238; 239 %m = and i25 %A, 16777215 ; max intermediate 16777215 (= 1 << 24)-1 240 %B = uitofp i25 %m to float 241 %C = fptoui float %B to i25 242 ret i25 %C 243} 244 245define i25 @consider_lowbits_masked_input(i25 %A) { 246; CHECK-LABEL: @consider_lowbits_masked_input( 247; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], -16777214 248; CHECK-NEXT: ret i25 [[M]] 249; 250 %m = and i25 %A, 16777218 ; Make use of the low zero bits - intermediate 16777218 (= 1 << 24 + 2) 251 %B = uitofp i25 %m to float 252 %C = fptoui float %B to i25 253 ret i25 %C 254} 255 256define i32 @overflow_masked_input(i32 %A) { 257; CHECK-LABEL: @overflow_masked_input( 258; CHECK-NEXT: [[M:%.*]] = and i32 [[A:%.*]], 16777217 259; CHECK-NEXT: [[B:%.*]] = uitofp nneg i32 [[M]] to float 260; CHECK-NEXT: [[C:%.*]] = fptoui float [[B]] to i32 261; CHECK-NEXT: ret i32 [[C]] 262; 263 %m = and i32 %A, 16777217 ; Negative test - intermediate 16777217 (= 1 << 24 + 1) 264 %B = uitofp i32 %m to float 265 %C = fptoui float %B to i32 266 ret i32 %C 267} 268 269; Clear the low bit - guarantees that the input is converted to FP without rounding. 270 271define i25 @low_masked_input(i25 %A) { 272; CHECK-LABEL: @low_masked_input( 273; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], -2 274; CHECK-NEXT: ret i25 [[M]] 275; 276 %m = and i25 %A, -2 277 %B = uitofp i25 %m to float 278 %C = fptoui float %B to i25 279 ret i25 %C 280} 281 282; Output is small enough to ensure exact cast (overflow produces poison). 283 284define i11 @s32_half_s11(i32 %x) { 285; CHECK-LABEL: @s32_half_s11( 286; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i11 287; CHECK-NEXT: ret i11 [[R]] 288; 289 %h = sitofp i32 %x to half 290 %r = fptosi half %h to i11 291 ret i11 %r 292} 293 294; Output is small enough to ensure exact cast (overflow produces poison). 295 296define i11 @s32_half_u11(i32 %x) { 297; CHECK-LABEL: @s32_half_u11( 298; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i11 299; CHECK-NEXT: ret i11 [[R]] 300; 301 %h = sitofp i32 %x to half 302 %r = fptoui half %h to i11 303 ret i11 %r 304} 305 306; Output is small enough to ensure exact cast (overflow produces poison). 307 308define i11 @u32_half_s11(i32 %x) { 309; CHECK-LABEL: @u32_half_s11( 310; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i11 311; CHECK-NEXT: ret i11 [[R]] 312; 313 %h = uitofp i32 %x to half 314 %r = fptosi half %h to i11 315 ret i11 %r 316} 317 318; Output is small enough to ensure exact cast (overflow produces poison). 319 320define i11 @u32_half_u11(i32 %x) { 321; CHECK-LABEL: @u32_half_u11( 322; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i11 323; CHECK-NEXT: ret i11 [[R]] 324; 325 %h = uitofp i32 %x to half 326 %r = fptoui half %h to i11 327 ret i11 %r 328} 329 330; Too many bits in output to ensure exact cast. 331 332define i12 @s32_half_s12(i32 %x) { 333; CHECK-LABEL: @s32_half_s12( 334; CHECK-NEXT: [[H:%.*]] = sitofp i32 [[X:%.*]] to half 335; CHECK-NEXT: [[R:%.*]] = fptosi half [[H]] to i12 336; CHECK-NEXT: ret i12 [[R]] 337; 338 %h = sitofp i32 %x to half 339 %r = fptosi half %h to i12 340 ret i12 %r 341} 342 343; Too many bits in output to ensure exact cast. 344 345define i12 @s32_half_u12(i32 %x) { 346; CHECK-LABEL: @s32_half_u12( 347; CHECK-NEXT: [[H:%.*]] = sitofp i32 [[X:%.*]] to half 348; CHECK-NEXT: [[R:%.*]] = fptoui half [[H]] to i12 349; CHECK-NEXT: ret i12 [[R]] 350; 351 %h = sitofp i32 %x to half 352 %r = fptoui half %h to i12 353 ret i12 %r 354} 355 356; TODO: This is safe to convert to trunc. 357 358define i12 @u32_half_s12(i32 %x) { 359; CHECK-LABEL: @u32_half_s12( 360; CHECK-NEXT: [[H:%.*]] = uitofp i32 [[X:%.*]] to half 361; CHECK-NEXT: [[R:%.*]] = fptosi half [[H]] to i12 362; CHECK-NEXT: ret i12 [[R]] 363; 364 %h = uitofp i32 %x to half 365 %r = fptosi half %h to i12 366 ret i12 %r 367} 368 369; Too many bits in output to ensure exact cast. 370 371define i12 @u32_half_u12(i32 %x) { 372; CHECK-LABEL: @u32_half_u12( 373; CHECK-NEXT: [[H:%.*]] = uitofp i32 [[X:%.*]] to half 374; CHECK-NEXT: [[R:%.*]] = fptoui half [[H]] to i12 375; CHECK-NEXT: ret i12 [[R]] 376; 377 %h = uitofp i32 %x to half 378 %r = fptoui half %h to i12 379 ret i12 %r 380} 381 382define <2 x i1> @i8_vec_sitofp_test1(<2 x i8> %A) { 383; CHECK-LABEL: @i8_vec_sitofp_test1( 384; CHECK-NEXT: ret <2 x i1> splat (i1 true) 385; 386 %B = sitofp <2 x i8> %A to <2 x double> 387 %C = fcmp ult <2 x double> %B, <double 128.0, double 128.0> 388 ret <2 x i1> %C 389} 390 391define <2 x i1> @i8_vec_sitofp_test2(<2 x i8> %A) { 392; CHECK-LABEL: @i8_vec_sitofp_test2( 393; CHECK-NEXT: ret <2 x i1> splat (i1 true) 394; 395 %B = sitofp <2 x i8> %A to <2 x double> 396 %C = fcmp ugt <2 x double> %B, <double -128.1, double -128.1> 397 ret <2 x i1> %C 398} 399 400define <2 x i1> @i8_vec_sitofp_test3(<2 x i8> %A) { 401; CHECK-LABEL: @i8_vec_sitofp_test3( 402; CHECK-NEXT: ret <2 x i1> splat (i1 true) 403; 404 %B = sitofp <2 x i8> %A to <2 x double> 405 %C = fcmp ule <2 x double> %B, <double 127.0, double 127.0> 406 ret <2 x i1> %C 407} 408 409define <2 x i1> @i8_vec_sitofp_test4(<2 x i8> %A) { 410; CHECK-LABEL: @i8_vec_sitofp_test4( 411; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[A:%.*]], splat (i8 127) 412; CHECK-NEXT: ret <2 x i1> [[C]] 413; 414 %B = sitofp <2 x i8> %A to <2 x double> 415 %C = fcmp ult <2 x double> %B, <double 127.0, double 127.0> 416 ret <2 x i1> %C 417} 418