1; Test switch instructions. 2 3; RUN: %p2i -i %s --insts | FileCheck %s 4; RUN: %p2i -i %s --args -notranslate -timing | \ 5; RUN: FileCheck --check-prefix=NOIR %s 6 7define internal void @testDefaultSwitch(i32 %a) { 8entry: 9 switch i32 %a, label %exit [ 10 ] 11exit: 12 ret void 13} 14 15; CHECK: define internal void @testDefaultSwitch(i32 %a) { 16; CHECK-NEXT: entry: 17; CHECK-NEXT: switch i32 %a, label %exit [ 18; CHECK-NEXT: ] 19; CHECK-NEXT: exit: 20; CHECK-NEXT: ret void 21; CHECK-NEXT: } 22 23define internal i32 @testSwitch(i32 %a) { 24entry: 25 switch i32 %a, label %sw.default [ 26 i32 1, label %sw.epilog 27 i32 2, label %sw.epilog 28 i32 3, label %sw.epilog 29 i32 7, label %sw.bb1 30 i32 8, label %sw.bb1 31 i32 15, label %sw.bb2 32 i32 14, label %sw.bb2 33 ] 34 35sw.default: ; preds = %entry 36 %add = add i32 %a, 27 37 br label %sw.epilog 38 39sw.bb1: ; preds = %entry, %entry 40 %phitmp = sub i32 21, %a 41 br label %sw.bb2 42 43sw.bb2: ; preds = %sw.bb1, %entry, %entry 44 %result.0 = phi i32 [ 1, %entry ], [ 1, %entry ], [ %phitmp, %sw.bb1 ] 45 br label %sw.epilog 46 47sw.epilog: ; preds = %sw.bb2, %sw.default, %entry, %entry, %entry 48 %result.1 = phi i32 [ %add, %sw.default ], [ %result.0, %sw.bb2 ], [ 17, %entry ], [ 17, %entry ], [ 17, %entry ] 49 ret i32 %result.1 50} 51 52; CHECK-NEXT: define internal i32 @testSwitch(i32 %a) { 53; CHECK-NEXT: entry: 54; CHECK-NEXT: switch i32 %a, label %sw.default [ 55; CHECK-NEXT: i32 1, label %sw.epilog 56; CHECK-NEXT: i32 2, label %sw.epilog 57; CHECK-NEXT: i32 3, label %sw.epilog 58; CHECK-NEXT: i32 7, label %sw.bb1 59; CHECK-NEXT: i32 8, label %sw.bb1 60; CHECK-NEXT: i32 15, label %sw.bb2 61; CHECK-NEXT: i32 14, label %sw.bb2 62; CHECK-NEXT: ] 63; CHECK-NEXT: sw.default: 64; CHECK-NEXT: %add = add i32 %a, 27 65; CHECK-NEXT: br label %sw.epilog 66; CHECK-NEXT: sw.bb1: 67; CHECK-NEXT: %phitmp = sub i32 21, %a 68; CHECK-NEXT: br label %sw.bb2 69; CHECK-NEXT: sw.bb2: 70; CHECK-NEXT: %result.0 = phi i32 [ 1, %entry ], [ 1, %entry ], [ %phitmp, %sw.bb1 ] 71; CHECK-NEXT: br label %sw.epilog 72; CHECK-NEXT: sw.epilog: 73; CHECK-NEXT: %result.1 = phi i32 [ %add, %sw.default ], [ %result.0, %sw.bb2 ], [ 17, %entry ], [ 17, %entry ], [ 17, %entry ] 74; CHECK-NEXT: ret i32 %result.1 75; CHECK-NEXT: } 76 77define internal void @testSignedI32Values(i32 %a) { 78entry: 79 switch i32 %a, label %labelDefault [ 80 i32 0, label %label0 81 i32 -1, label %labelM1 82 i32 3, label %labelOther 83 i32 -3, label %labelOther 84 i32 -2147483648, label %labelMin ; min signed i32 85 i32 2147483647, label %labelMax ; max signed i32 86 ] 87labelDefault: 88 ret void 89label0: 90 ret void 91labelM1: 92 ret void 93labelMin: 94 ret void 95labelMax: 96 ret void 97labelOther: 98 ret void 99} 100 101; CHECK-NEXT: define internal void @testSignedI32Values(i32 %a) { 102; CHECK-NEXT: entry: 103; CHECK-NEXT: switch i32 %a, label %labelDefault [ 104; CHECK-NEXT: i32 0, label %label0 105; CHECK-NEXT: i32 -1, label %labelM1 106; CHECK-NEXT: i32 3, label %labelOther 107; CHECK-NEXT: i32 -3, label %labelOther 108; CHECK-NEXT: i32 -2147483648, label %labelMin 109; CHECK-NEXT: i32 2147483647, label %labelMax 110; CHECK-NEXT: ] 111; CHECK-NEXT: labelDefault: 112; CHECK-NEXT: ret void 113; CHECK-NEXT: label0: 114; CHECK-NEXT: ret void 115; CHECK-NEXT: labelM1: 116; CHECK-NEXT: ret void 117; CHECK-NEXT: labelMin: 118; CHECK-NEXT: ret void 119; CHECK-NEXT: labelMax: 120; CHECK-NEXT: ret void 121; CHECK-NEXT: labelOther: 122; CHECK-NEXT: ret void 123; CHECK-NEXT: } 124 125; Test values that cross signed i32 size boundaries. 126define internal void @testSignedI32Boundary(i32 %a) { 127entry: 128 switch i32 %a, label %exit [ 129 i32 -2147483649, label %exit ; min signed i32 - 1 130 i32 2147483648, label %exit ; max signed i32 + 1 131 ] 132exit: 133 ret void 134} 135 136; CHECK-NEXT: define internal void @testSignedI32Boundary(i32 %a) { 137; CHECK-NEXT: entry: 138; CHECK-NEXT: switch i32 %a, label %exit [ 139; CHECK-NEXT: i32 2147483647, label %exit 140; CHECK-NEXT: i32 -2147483648, label %exit 141; CHECK-NEXT: ] 142; CHECK-NEXT: exit: 143; CHECK-NEXT: ret void 144; CHECK-NEXT: } 145 146define internal void @testUnsignedI32Values(i32 %a) { 147entry: 148 switch i32 %a, label %exit [ 149 i32 0, label %exit 150 i32 2147483647, label %exit ; max signed i32 151 i32 4294967295, label %exit ; max unsigned i32 152 ] 153exit: 154 ret void 155} 156 157; CHECK-NEXT: define internal void @testUnsignedI32Values(i32 %a) { 158; CHECK-NEXT: entry: 159; CHECK-NEXT: switch i32 %a, label %exit [ 160; CHECK-NEXT: i32 0, label %exit 161; CHECK-NEXT: i32 2147483647, label %exit 162; ; Note that -1 is signed version of 4294967295 163; CHECK-NEXT: i32 -1, label %exit 164; CHECK-NEXT: ] 165; CHECK-NEXT: exit: 166; CHECK-NEXT: ret void 167; CHECK-NEXT: } 168 169; Test values that cross unsigned i32 boundaries. 170define internal void @testUnsignedI32Boundary(i32 %a) { 171entry: 172 switch i32 %a, label %exit [ 173 i32 4294967296, label %exit ; max unsigned i32 + 1 174 ] 175exit: 176 ret void 177} 178 179; CHECK-NEXT: define internal void @testUnsignedI32Boundary(i32 %a) { 180; CHECK-NEXT: entry: 181; CHECK-NEXT: switch i32 %a, label %exit [ 182; CHECK-NEXT: i32 0, label %exit 183; CHECK-NEXT: ] 184; CHECK-NEXT: exit: 185; CHECK-NEXT: ret void 186; CHECK-NEXT: } 187 188define internal void @testSignedI64Values(i64 %a) { 189entry: 190 switch i64 %a, label %exit [ 191 i64 0, label %exit 192 i64 -9223372036854775808, label %exit ; min signed i64 193 i64 9223372036854775807, label %exit ; max signed i64 194 ] 195exit: 196 ret void 197} 198 199; CHECK-NEXT: define internal void @testSignedI64Values(i64 %a) { 200; CHECK-NEXT: entry: 201; CHECK-NEXT: switch i64 %a, label %exit [ 202; CHECK-NEXT: i64 0, label %exit 203; CHECK-NEXT: i64 -9223372036854775808, label %exit 204; CHECK-NEXT: i64 9223372036854775807, label %exit 205; CHECK-NEXT: ] 206; CHECK-NEXT: exit: 207; CHECK-NEXT: ret void 208; CHECK-NEXT: } 209 210; Test values that cross signed i64 size boundaries. 211define internal void @testSignedI64Boundary(i64 %a) { 212entry: 213 switch i64 %a, label %exit [ 214 i64 0, label %exit 215 i64 -9223372036854775809, label %exit ; min signed i64 - 1 216 i64 9223372036854775808, label %exit ; max signed i64 + 1 217 ] 218exit: 219 ret void 220} 221 222; CHECK-NEXT: define internal void @testSignedI64Boundary(i64 %a) { 223; CHECK-NEXT: entry: 224; CHECK-NEXT: switch i64 %a, label %exit [ 225; CHECK-NEXT: i64 0, label %exit 226; CHECK-NEXT: i64 9223372036854775807, label %exit 227; CHECK-NEXT: i64 -9223372036854775808, label %exit 228; CHECK-NEXT: ] 229; CHECK-NEXT: exit: 230; CHECK-NEXT: ret void 231; CHECK-NEXT: } 232 233define internal void @testUnsignedI64Values(i64 %a) { 234entry: 235 switch i64 %a, label %exit [ 236 i64 0, label %exit 237 i64 9223372036854775807, label %exit ; max signed i64 238 i64 18446744073709551615, label %exit ; max unsigned i64 239 ] 240exit: 241 ret void 242} 243 244; CHECK-NEXT: define internal void @testUnsignedI64Values(i64 %a) { 245; CHECK-NEXT: entry: 246; CHECK-NEXT: switch i64 %a, label %exit [ 247; CHECK-NEXT: i64 0, label %exit 248; CHECK-NEXT: i64 9223372036854775807, label %exit 249; CHECK-NEXT: i64 -1, label %exit 250; CHECK-NEXT: ] 251; CHECK-NEXT: exit: 252; CHECK-NEXT: ret void 253; CHECK-NEXT: } 254 255; Test values that cross unsigned i64 size boundaries. 256define internal void @testUnsignedI64Boundary(i64 %a) { 257entry: 258 switch i64 %a, label %exit [ 259 i64 18446744073709551616, label %exit ; max unsigned i64 + 1 260 ] 261exit: 262 ret void 263} 264 265; CHECK-NEXT: define internal void @testUnsignedI64Boundary(i64 %a) { 266; CHECK-NEXT: entry: 267; CHECK-NEXT: switch i64 %a, label %exit [ 268; CHECK-NEXT: i64 0, label %exit 269; CHECK-NEXT: ] 270; CHECK-NEXT: exit: 271; CHECK-NEXT: ret void 272; CHECK-NEXT: } 273 274define internal void @testSignedI16Values(i32 %p) { 275entry: 276 %a = trunc i32 %p to i16 277 switch i16 %a, label %exit [ 278 i16 0, label %exit 279 i16 -1, label %exit 280 i16 3, label %exit 281 i16 -3, label %exit 282 i16 -32768, label %exit ; min signed i16 283 i16 32767, label %exit ; max unsigned i16 284 ] 285exit: 286 ret void 287} 288 289; CHECK-NEXT: define internal void @testSignedI16Values(i32 %p) { 290; CHECK-NEXT: entry: 291; CHECK-NEXT: %a = trunc i32 %p to i16 292; CHECK-NEXT: switch i16 %a, label %exit [ 293; CHECK-NEXT: i16 0, label %exit 294; CHECK-NEXT: i16 -1, label %exit 295; CHECK-NEXT: i16 3, label %exit 296; CHECK-NEXT: i16 -3, label %exit 297; CHECK-NEXT: i16 -32768, label %exit 298; CHECK-NEXT: i16 32767, label %exit 299; CHECK-NEXT: ] 300; CHECK-NEXT: exit: 301; CHECK-NEXT: ret void 302; CHECK-NEXT: } 303 304; Test values that cross signed i16 size boundaries. 305define internal void @testSignedI16Boundary(i32 %p) { 306entry: 307 %a = trunc i32 %p to i16 308 switch i16 %a, label %exit [ 309 i16 -32769, label %exit ; min signed i16 - 1 310 i16 32768, label %exit ; max unsigned i16 + 1 311 ] 312exit: 313 ret void 314} 315 316; CHECK-NEXT: define internal void @testSignedI16Boundary(i32 %p) { 317; CHECK-NEXT: entry: 318; CHECK-NEXT: %a = trunc i32 %p to i16 319; CHECK-NEXT: switch i16 %a, label %exit [ 320; CHECK-NEXT: i16 32767, label %exit 321; CHECK-NEXT: i16 -32768, label %exit 322; CHECK-NEXT: ] 323; CHECK-NEXT: exit: 324; CHECK-NEXT: ret void 325; CHECK-NEXT: } 326 327define internal void @testUnsignedI16Values(i32 %p) { 328entry: 329 %a = trunc i32 %p to i16 330 switch i16 %a, label %exit [ 331 i16 0, label %exit 332 i16 32767, label %exit ; max signed i16 333 i16 65535, label %exit ; max unsigned i16 334 ] 335exit: 336 ret void 337} 338 339; CHECK-NEXT: define internal void @testUnsignedI16Values(i32 %p) { 340; CHECK-NEXT: entry: 341; CHECK-NEXT: %a = trunc i32 %p to i16 342; CHECK-NEXT: switch i16 %a, label %exit [ 343; CHECK-NEXT: i16 0, label %exit 344; CHECK-NEXT: i16 32767, label %exit 345; ; Note that -1 is signed version of 65535 346; CHECK-NEXT: i16 -1, label %exit 347; CHECK-NEXT: ] 348; CHECK-NEXT: exit: 349; CHECK-NEXT: ret void 350; CHECK-NEXT: } 351 352; Test values that cross unsigned i16 size boundaries. 353define internal void @testUnsignedI16Boundary(i32 %p) { 354entry: 355 %a = trunc i32 %p to i16 356 switch i16 %a, label %exit [ 357 i16 65536, label %exit ; max unsigned i16 + 1 358 ] 359exit: 360 ret void 361} 362 363; CHECK-NEXT: define internal void @testUnsignedI16Boundary(i32 %p) { 364; CHECK-NEXT: entry: 365; CHECK-NEXT: %a = trunc i32 %p to i16 366; CHECK-NEXT: switch i16 %a, label %exit [ 367; CHECK-NEXT: i16 0, label %exit 368; CHECK-NEXT: ] 369; CHECK-NEXT: exit: 370; CHECK-NEXT: ret void 371; CHECK-NEXT: } 372 373define internal void @testSignedI8Values(i32 %p) { 374entry: 375 %a = trunc i32 %p to i8 376 switch i8 %a, label %exit [ 377 i8 0, label %exit 378 i8 -1, label %exit 379 i8 3, label %exit 380 i8 -3, label %exit 381 i8 -128, label %exit ; min signed i8 382 i8 127, label %exit ; max unsigned i8 383 ] 384exit: 385 ret void 386} 387 388; CHECK-NEXT: define internal void @testSignedI8Values(i32 %p) { 389; CHECK-NEXT: entry: 390; CHECK-NEXT: %a = trunc i32 %p to i8 391; CHECK-NEXT: switch i8 %a, label %exit [ 392; CHECK-NEXT: i8 0, label %exit 393; CHECK-NEXT: i8 -1, label %exit 394; CHECK-NEXT: i8 3, label %exit 395; CHECK-NEXT: i8 -3, label %exit 396; CHECK-NEXT: i8 -128, label %exit 397; CHECK-NEXT: i8 127, label %exit 398; CHECK-NEXT: ] 399; CHECK-NEXT: exit: 400; CHECK-NEXT: ret void 401; CHECK-NEXT: } 402 403; Test values that cross signed i8 size boundaries. 404define internal void @testSignedI8Boundary(i32 %p) { 405entry: 406 %a = trunc i32 %p to i8 407 switch i8 %a, label %exit [ 408 i8 -129, label %exit ; min signed i8 - 1 409 i8 128, label %exit ; max unsigned i8 + 1 410 ] 411exit: 412 ret void 413} 414 415; CHECK-NEXT: define internal void @testSignedI8Boundary(i32 %p) { 416; CHECK-NEXT: entry: 417; CHECK-NEXT: %a = trunc i32 %p to i8 418; CHECK-NEXT: switch i8 %a, label %exit [ 419; CHECK-NEXT: i8 127, label %exit 420; CHECK-NEXT: i8 -128, label %exit 421; CHECK-NEXT: ] 422; CHECK-NEXT: exit: 423; CHECK-NEXT: ret void 424; CHECK-NEXT: } 425 426 427define internal void @testUnsignedI8Values(i32 %p) { 428entry: 429 %a = trunc i32 %p to i8 430 switch i8 %a, label %exit [ 431 i8 0, label %exit 432 i8 127, label %exit ; max signed i8 433 i8 255, label %exit ; max unsigned i8 434 ] 435exit: 436 ret void 437} 438 439; CHECK-NEXT: define internal void @testUnsignedI8Values(i32 %p) { 440; CHECK-NEXT: entry: 441; CHECK-NEXT: %a = trunc i32 %p to i8 442; CHECK-NEXT: switch i8 %a, label %exit [ 443; CHECK-NEXT: i8 0, label %exit 444; CHECK-NEXT: i8 127, label %exit 445; ; Note that -1 is signed version of 255 446; CHECK-NEXT: i8 -1, label %exit 447; CHECK-NEXT: ] 448; CHECK-NEXT: exit: 449; CHECK-NEXT: ret void 450; CHECK-NEXT: } 451 452; Test values that cross unsigned i8 size boundaries. 453define internal void @testUnsignedI8Boundary(i32 %p) { 454entry: 455 %a = trunc i32 %p to i8 456 switch i8 %a, label %exit [ 457 i8 256, label %exit ; max unsigned i8 458 ] 459exit: 460 ret void 461} 462 463; CHECK-NEXT: define internal void @testUnsignedI8Boundary(i32 %p) { 464; CHECK-NEXT: entry: 465; CHECK-NEXT: %a = trunc i32 %p to i8 466; CHECK-NEXT: switch i8 %a, label %exit [ 467; CHECK-NEXT: i8 0, label %exit 468; CHECK-NEXT: ] 469; CHECK-NEXT: exit: 470; CHECK-NEXT: ret void 471; CHECK-NEXT: } 472 473define internal void @testI1Values(i32 %p) { 474entry: 475 %a = trunc i32 %p to i1 476 switch i1 %a, label %exit [ 477 i1 true, label %exit 478 i1 false, label %exit 479 ] 480exit: 481 ret void 482} 483 484; CHECK-NEXT: define internal void @testI1Values(i32 %p) { 485; CHECK-NEXT: entry: 486; CHECK-NEXT: %a = trunc i32 %p to i1 487; CHECK-NEXT: switch i1 %a, label %exit [ 488; CHECK-NEXT: i1 -1, label %exit 489; CHECK-NEXT: i1 0, label %exit 490; CHECK-NEXT: ] 491; CHECK-NEXT: exit: 492; CHECK-NEXT: ret void 493; CHECK-NEXT: } 494 495; NOIR: Total across all functions 496