1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefixes=RV32,RV32I %s 4; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi=ilp32 -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefixes=RV32,RV32IF %s 6; RUN: llc -mtriple=riscv64 -target-abi=lp64 -verify-machineinstrs < %s \ 7; RUN: | FileCheck -check-prefixes=RV64,RV64I %s 8; RUN: llc -mtriple=riscv64 -mattr=+f,+d -target-abi=lp64 -verify-machineinstrs < %s \ 9; RUN: | FileCheck -check-prefixes=RV64,RV64IFD %s 10 11;; This tests how good we are at materialising constants using `select`. The aim 12;; is that we do so without a branch if possible (at the moment our lowering of 13;; select always introduces a branch). 14;; 15;; Currently the hook `convertSelectOfConstantsToMath` only is useful when the 16;; constants are either 1 away from each other, or one is a power of two and 17;; the other is zero. 18 19define signext i32 @select_const_int_easy(i1 zeroext %a) nounwind { 20; RV32-LABEL: select_const_int_easy: 21; RV32: # %bb.0: 22; RV32-NEXT: ret 23; 24; RV64-LABEL: select_const_int_easy: 25; RV64: # %bb.0: 26; RV64-NEXT: ret 27 %1 = select i1 %a, i32 1, i32 0 28 ret i32 %1 29} 30 31define signext i32 @select_const_int_one_away(i1 zeroext %a) nounwind { 32; RV32-LABEL: select_const_int_one_away: 33; RV32: # %bb.0: 34; RV32-NEXT: li a1, 4 35; RV32-NEXT: sub a0, a1, a0 36; RV32-NEXT: ret 37; 38; RV64-LABEL: select_const_int_one_away: 39; RV64: # %bb.0: 40; RV64-NEXT: li a1, 4 41; RV64-NEXT: sub a0, a1, a0 42; RV64-NEXT: ret 43 %1 = select i1 %a, i32 3, i32 4 44 ret i32 %1 45} 46 47define signext i32 @select_const_int_pow2_zero(i1 zeroext %a) nounwind { 48; RV32-LABEL: select_const_int_pow2_zero: 49; RV32: # %bb.0: 50; RV32-NEXT: slli a0, a0, 2 51; RV32-NEXT: ret 52; 53; RV64-LABEL: select_const_int_pow2_zero: 54; RV64: # %bb.0: 55; RV64-NEXT: slli a0, a0, 2 56; RV64-NEXT: ret 57 %1 = select i1 %a, i32 4, i32 0 58 ret i32 %1 59} 60 61define signext i32 @select_const_int_harder(i1 zeroext %a) nounwind { 62; RV32-LABEL: select_const_int_harder: 63; RV32: # %bb.0: 64; RV32-NEXT: bnez a0, .LBB3_2 65; RV32-NEXT: # %bb.1: 66; RV32-NEXT: li a0, 38 67; RV32-NEXT: ret 68; RV32-NEXT: .LBB3_2: 69; RV32-NEXT: li a0, 6 70; RV32-NEXT: ret 71; 72; RV64-LABEL: select_const_int_harder: 73; RV64: # %bb.0: 74; RV64-NEXT: bnez a0, .LBB3_2 75; RV64-NEXT: # %bb.1: 76; RV64-NEXT: li a0, 38 77; RV64-NEXT: ret 78; RV64-NEXT: .LBB3_2: 79; RV64-NEXT: li a0, 6 80; RV64-NEXT: ret 81 %1 = select i1 %a, i32 6, i32 38 82 ret i32 %1 83} 84 85define float @select_const_fp(i1 zeroext %a) nounwind { 86; RV32I-LABEL: select_const_fp: 87; RV32I: # %bb.0: 88; RV32I-NEXT: mv a1, a0 89; RV32I-NEXT: lui a0, 263168 90; RV32I-NEXT: bnez a1, .LBB4_2 91; RV32I-NEXT: # %bb.1: 92; RV32I-NEXT: lui a0, 264192 93; RV32I-NEXT: .LBB4_2: 94; RV32I-NEXT: ret 95; 96; RV32IF-LABEL: select_const_fp: 97; RV32IF: # %bb.0: 98; RV32IF-NEXT: bnez a0, .LBB4_2 99; RV32IF-NEXT: # %bb.1: 100; RV32IF-NEXT: lui a0, 264192 101; RV32IF-NEXT: j .LBB4_3 102; RV32IF-NEXT: .LBB4_2: 103; RV32IF-NEXT: lui a0, 263168 104; RV32IF-NEXT: .LBB4_3: 105; RV32IF-NEXT: fmv.w.x fa5, a0 106; RV32IF-NEXT: fmv.x.w a0, fa5 107; RV32IF-NEXT: ret 108; 109; RV64I-LABEL: select_const_fp: 110; RV64I: # %bb.0: 111; RV64I-NEXT: mv a1, a0 112; RV64I-NEXT: lui a0, 263168 113; RV64I-NEXT: bnez a1, .LBB4_2 114; RV64I-NEXT: # %bb.1: 115; RV64I-NEXT: lui a0, 264192 116; RV64I-NEXT: .LBB4_2: 117; RV64I-NEXT: ret 118; 119; RV64IFD-LABEL: select_const_fp: 120; RV64IFD: # %bb.0: 121; RV64IFD-NEXT: bnez a0, .LBB4_2 122; RV64IFD-NEXT: # %bb.1: 123; RV64IFD-NEXT: lui a0, 264192 124; RV64IFD-NEXT: j .LBB4_3 125; RV64IFD-NEXT: .LBB4_2: 126; RV64IFD-NEXT: lui a0, 263168 127; RV64IFD-NEXT: .LBB4_3: 128; RV64IFD-NEXT: fmv.w.x fa5, a0 129; RV64IFD-NEXT: fmv.x.w a0, fa5 130; RV64IFD-NEXT: ret 131 %1 = select i1 %a, float 3.0, float 4.0 132 ret float %1 133} 134 135define signext i32 @select_eq_zero_negone(i32 signext %a, i32 signext %b) nounwind { 136; RV32-LABEL: select_eq_zero_negone: 137; RV32: # %bb.0: 138; RV32-NEXT: xor a0, a0, a1 139; RV32-NEXT: snez a0, a0 140; RV32-NEXT: addi a0, a0, -1 141; RV32-NEXT: ret 142; 143; RV64-LABEL: select_eq_zero_negone: 144; RV64: # %bb.0: 145; RV64-NEXT: xor a0, a0, a1 146; RV64-NEXT: snez a0, a0 147; RV64-NEXT: addi a0, a0, -1 148; RV64-NEXT: ret 149 %1 = icmp eq i32 %a, %b 150 %2 = select i1 %1, i32 -1, i32 0 151 ret i32 %2 152} 153 154define signext i32 @select_ne_zero_negone(i32 signext %a, i32 signext %b) nounwind { 155; RV32-LABEL: select_ne_zero_negone: 156; RV32: # %bb.0: 157; RV32-NEXT: xor a0, a0, a1 158; RV32-NEXT: seqz a0, a0 159; RV32-NEXT: addi a0, a0, -1 160; RV32-NEXT: ret 161; 162; RV64-LABEL: select_ne_zero_negone: 163; RV64: # %bb.0: 164; RV64-NEXT: xor a0, a0, a1 165; RV64-NEXT: seqz a0, a0 166; RV64-NEXT: addi a0, a0, -1 167; RV64-NEXT: ret 168 %1 = icmp ne i32 %a, %b 169 %2 = select i1 %1, i32 -1, i32 0 170 ret i32 %2 171} 172 173define signext i32 @select_sgt_zero_negone(i32 signext %a, i32 signext %b) nounwind { 174; RV32-LABEL: select_sgt_zero_negone: 175; RV32: # %bb.0: 176; RV32-NEXT: slt a0, a1, a0 177; RV32-NEXT: neg a0, a0 178; RV32-NEXT: ret 179; 180; RV64-LABEL: select_sgt_zero_negone: 181; RV64: # %bb.0: 182; RV64-NEXT: slt a0, a1, a0 183; RV64-NEXT: neg a0, a0 184; RV64-NEXT: ret 185 %1 = icmp sgt i32 %a, %b 186 %2 = select i1 %1, i32 -1, i32 0 187 ret i32 %2 188} 189 190define signext i32 @select_slt_zero_negone(i32 signext %a, i32 signext %b) nounwind { 191; RV32-LABEL: select_slt_zero_negone: 192; RV32: # %bb.0: 193; RV32-NEXT: slt a0, a0, a1 194; RV32-NEXT: neg a0, a0 195; RV32-NEXT: ret 196; 197; RV64-LABEL: select_slt_zero_negone: 198; RV64: # %bb.0: 199; RV64-NEXT: slt a0, a0, a1 200; RV64-NEXT: neg a0, a0 201; RV64-NEXT: ret 202 %1 = icmp slt i32 %a, %b 203 %2 = select i1 %1, i32 -1, i32 0 204 ret i32 %2 205} 206 207define signext i32 @select_sge_zero_negone(i32 signext %a, i32 signext %b) nounwind { 208; RV32-LABEL: select_sge_zero_negone: 209; RV32: # %bb.0: 210; RV32-NEXT: slt a0, a0, a1 211; RV32-NEXT: addi a0, a0, -1 212; RV32-NEXT: ret 213; 214; RV64-LABEL: select_sge_zero_negone: 215; RV64: # %bb.0: 216; RV64-NEXT: slt a0, a0, a1 217; RV64-NEXT: addi a0, a0, -1 218; RV64-NEXT: ret 219 %1 = icmp sge i32 %a, %b 220 %2 = select i1 %1, i32 -1, i32 0 221 ret i32 %2 222} 223 224define signext i32 @select_sle_zero_negone(i32 signext %a, i32 signext %b) nounwind { 225; RV32-LABEL: select_sle_zero_negone: 226; RV32: # %bb.0: 227; RV32-NEXT: slt a0, a1, a0 228; RV32-NEXT: addi a0, a0, -1 229; RV32-NEXT: ret 230; 231; RV64-LABEL: select_sle_zero_negone: 232; RV64: # %bb.0: 233; RV64-NEXT: slt a0, a1, a0 234; RV64-NEXT: addi a0, a0, -1 235; RV64-NEXT: ret 236 %1 = icmp sle i32 %a, %b 237 %2 = select i1 %1, i32 -1, i32 0 238 ret i32 %2 239} 240 241define signext i32 @select_ugt_zero_negone(i32 signext %a, i32 signext %b) nounwind { 242; RV32-LABEL: select_ugt_zero_negone: 243; RV32: # %bb.0: 244; RV32-NEXT: sltu a0, a1, a0 245; RV32-NEXT: neg a0, a0 246; RV32-NEXT: ret 247; 248; RV64-LABEL: select_ugt_zero_negone: 249; RV64: # %bb.0: 250; RV64-NEXT: sltu a0, a1, a0 251; RV64-NEXT: neg a0, a0 252; RV64-NEXT: ret 253 %1 = icmp ugt i32 %a, %b 254 %2 = select i1 %1, i32 -1, i32 0 255 ret i32 %2 256} 257 258define signext i32 @select_ult_zero_negone(i32 signext %a, i32 signext %b) nounwind { 259; RV32-LABEL: select_ult_zero_negone: 260; RV32: # %bb.0: 261; RV32-NEXT: sltu a0, a0, a1 262; RV32-NEXT: neg a0, a0 263; RV32-NEXT: ret 264; 265; RV64-LABEL: select_ult_zero_negone: 266; RV64: # %bb.0: 267; RV64-NEXT: sltu a0, a0, a1 268; RV64-NEXT: neg a0, a0 269; RV64-NEXT: ret 270 %1 = icmp ult i32 %a, %b 271 %2 = select i1 %1, i32 -1, i32 0 272 ret i32 %2 273} 274 275define signext i32 @select_uge_zero_negone(i32 signext %a, i32 signext %b) nounwind { 276; RV32-LABEL: select_uge_zero_negone: 277; RV32: # %bb.0: 278; RV32-NEXT: sltu a0, a0, a1 279; RV32-NEXT: addi a0, a0, -1 280; RV32-NEXT: ret 281; 282; RV64-LABEL: select_uge_zero_negone: 283; RV64: # %bb.0: 284; RV64-NEXT: sltu a0, a0, a1 285; RV64-NEXT: addi a0, a0, -1 286; RV64-NEXT: ret 287 %1 = icmp uge i32 %a, %b 288 %2 = select i1 %1, i32 -1, i32 0 289 ret i32 %2 290} 291 292define signext i32 @select_ule_zero_negone(i32 signext %a, i32 signext %b) nounwind { 293; RV32-LABEL: select_ule_zero_negone: 294; RV32: # %bb.0: 295; RV32-NEXT: sltu a0, a1, a0 296; RV32-NEXT: addi a0, a0, -1 297; RV32-NEXT: ret 298; 299; RV64-LABEL: select_ule_zero_negone: 300; RV64: # %bb.0: 301; RV64-NEXT: sltu a0, a1, a0 302; RV64-NEXT: addi a0, a0, -1 303; RV64-NEXT: ret 304 %1 = icmp ule i32 %a, %b 305 %2 = select i1 %1, i32 -1, i32 0 306 ret i32 %2 307} 308 309define i32 @select_eq_1_2(i32 signext %a, i32 signext %b) { 310; RV32-LABEL: select_eq_1_2: 311; RV32: # %bb.0: 312; RV32-NEXT: xor a0, a0, a1 313; RV32-NEXT: snez a0, a0 314; RV32-NEXT: addi a0, a0, 1 315; RV32-NEXT: ret 316; 317; RV64-LABEL: select_eq_1_2: 318; RV64: # %bb.0: 319; RV64-NEXT: xor a0, a0, a1 320; RV64-NEXT: snez a0, a0 321; RV64-NEXT: addi a0, a0, 1 322; RV64-NEXT: ret 323 %1 = icmp eq i32 %a, %b 324 %2 = select i1 %1, i32 1, i32 2 325 ret i32 %2 326} 327 328define i32 @select_ne_1_2(i32 signext %a, i32 signext %b) { 329; RV32-LABEL: select_ne_1_2: 330; RV32: # %bb.0: 331; RV32-NEXT: xor a0, a0, a1 332; RV32-NEXT: seqz a0, a0 333; RV32-NEXT: addi a0, a0, 1 334; RV32-NEXT: ret 335; 336; RV64-LABEL: select_ne_1_2: 337; RV64: # %bb.0: 338; RV64-NEXT: xor a0, a0, a1 339; RV64-NEXT: seqz a0, a0 340; RV64-NEXT: addi a0, a0, 1 341; RV64-NEXT: ret 342 %1 = icmp ne i32 %a, %b 343 %2 = select i1 %1, i32 1, i32 2 344 ret i32 %2 345} 346 347define i32 @select_eq_10000_10001(i32 signext %a, i32 signext %b) { 348; RV32-LABEL: select_eq_10000_10001: 349; RV32: # %bb.0: 350; RV32-NEXT: xor a0, a0, a1 351; RV32-NEXT: lui a1, 2 352; RV32-NEXT: seqz a0, a0 353; RV32-NEXT: addi a1, a1, 1810 354; RV32-NEXT: sub a0, a1, a0 355; RV32-NEXT: ret 356; 357; RV64-LABEL: select_eq_10000_10001: 358; RV64: # %bb.0: 359; RV64-NEXT: xor a0, a0, a1 360; RV64-NEXT: lui a1, 2 361; RV64-NEXT: seqz a0, a0 362; RV64-NEXT: addiw a1, a1, 1810 363; RV64-NEXT: sub a0, a1, a0 364; RV64-NEXT: ret 365 %1 = icmp eq i32 %a, %b 366 %2 = select i1 %1, i32 10001, i32 10002 367 ret i32 %2 368} 369 370define i32 @select_ne_10001_10002(i32 signext %a, i32 signext %b) { 371; RV32-LABEL: select_ne_10001_10002: 372; RV32: # %bb.0: 373; RV32-NEXT: xor a0, a0, a1 374; RV32-NEXT: lui a1, 2 375; RV32-NEXT: snez a0, a0 376; RV32-NEXT: addi a1, a1, 1810 377; RV32-NEXT: sub a0, a1, a0 378; RV32-NEXT: ret 379; 380; RV64-LABEL: select_ne_10001_10002: 381; RV64: # %bb.0: 382; RV64-NEXT: xor a0, a0, a1 383; RV64-NEXT: lui a1, 2 384; RV64-NEXT: snez a0, a0 385; RV64-NEXT: addiw a1, a1, 1810 386; RV64-NEXT: sub a0, a1, a0 387; RV64-NEXT: ret 388 %1 = icmp ne i32 %a, %b 389 %2 = select i1 %1, i32 10001, i32 10002 390 ret i32 %2 391} 392 393define i32 @select_slt_zero_constant1_constant2(i32 signext %x) { 394; RV32-LABEL: select_slt_zero_constant1_constant2: 395; RV32: # %bb.0: 396; RV32-NEXT: srai a0, a0, 31 397; RV32-NEXT: andi a0, a0, 10 398; RV32-NEXT: addi a0, a0, -3 399; RV32-NEXT: ret 400; 401; RV64-LABEL: select_slt_zero_constant1_constant2: 402; RV64: # %bb.0: 403; RV64-NEXT: srai a0, a0, 63 404; RV64-NEXT: andi a0, a0, 10 405; RV64-NEXT: addi a0, a0, -3 406; RV64-NEXT: ret 407 %cmp = icmp slt i32 %x, 0 408 %cond = select i1 %cmp, i32 7, i32 -3 409 ret i32 %cond 410} 411 412define i32 @select_sgt_negative_one_constant1_constant2(i32 signext %x) { 413; RV32-LABEL: select_sgt_negative_one_constant1_constant2: 414; RV32: # %bb.0: 415; RV32-NEXT: srai a0, a0, 31 416; RV32-NEXT: andi a0, a0, -10 417; RV32-NEXT: addi a0, a0, 7 418; RV32-NEXT: ret 419; 420; RV64-LABEL: select_sgt_negative_one_constant1_constant2: 421; RV64: # %bb.0: 422; RV64-NEXT: srai a0, a0, 63 423; RV64-NEXT: andi a0, a0, -10 424; RV64-NEXT: addi a0, a0, 7 425; RV64-NEXT: ret 426 %cmp = icmp sgt i32 %x, -1 427 %cond = select i1 %cmp, i32 7, i32 -3 428 ret i32 %cond 429} 430