341 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi=ilp32 -verify-machineinstrs < %s \3; RUN: | FileCheck %s -check-prefix=RV32I4; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi=lp64 -verify-machineinstrs < %s \5; RUN: | FileCheck %s -check-prefix=RV64I6 7; Selects of wide values are split into two selects, which can easily cause8; unnecessary control flow. Here we check some cases where we can currently9; emit a sequence of selects with shared control flow.10 11define i64 @cmovcc64(i32 signext %a, i64 %b, i64 %c) nounwind {12; RV32I-LABEL: cmovcc64:13; RV32I: # %bb.0: # %entry14; RV32I-NEXT: li a5, 12315; RV32I-NEXT: beq a0, a5, .LBB0_216; RV32I-NEXT: # %bb.1: # %entry17; RV32I-NEXT: mv a1, a318; RV32I-NEXT: mv a2, a419; RV32I-NEXT: .LBB0_2: # %entry20; RV32I-NEXT: mv a0, a121; RV32I-NEXT: mv a1, a222; RV32I-NEXT: ret23;24; RV64I-LABEL: cmovcc64:25; RV64I: # %bb.0: # %entry26; RV64I-NEXT: li a3, 12327; RV64I-NEXT: beq a0, a3, .LBB0_228; RV64I-NEXT: # %bb.1: # %entry29; RV64I-NEXT: mv a1, a230; RV64I-NEXT: .LBB0_2: # %entry31; RV64I-NEXT: mv a0, a132; RV64I-NEXT: ret33entry:34 %cmp = icmp eq i32 %a, 12335 %cond = select i1 %cmp, i64 %b, i64 %c36 ret i64 %cond37}38 39define i128 @cmovcc128(i64 signext %a, i128 %b, i128 %c) nounwind {40; RV32I-LABEL: cmovcc128:41; RV32I: # %bb.0: # %entry42; RV32I-NEXT: xori a1, a1, 12343; RV32I-NEXT: or a1, a1, a244; RV32I-NEXT: mv a2, a345; RV32I-NEXT: beqz a1, .LBB1_246; RV32I-NEXT: # %bb.1: # %entry47; RV32I-NEXT: mv a2, a448; RV32I-NEXT: .LBB1_2: # %entry49; RV32I-NEXT: beqz a1, .LBB1_550; RV32I-NEXT: # %bb.3: # %entry51; RV32I-NEXT: addi a5, a4, 452; RV32I-NEXT: bnez a1, .LBB1_653; RV32I-NEXT: .LBB1_4:54; RV32I-NEXT: addi a6, a3, 855; RV32I-NEXT: j .LBB1_756; RV32I-NEXT: .LBB1_5:57; RV32I-NEXT: addi a5, a3, 458; RV32I-NEXT: beqz a1, .LBB1_459; RV32I-NEXT: .LBB1_6: # %entry60; RV32I-NEXT: addi a6, a4, 861; RV32I-NEXT: .LBB1_7: # %entry62; RV32I-NEXT: lw a2, 0(a2)63; RV32I-NEXT: lw a5, 0(a5)64; RV32I-NEXT: lw a6, 0(a6)65; RV32I-NEXT: beqz a1, .LBB1_966; RV32I-NEXT: # %bb.8: # %entry67; RV32I-NEXT: addi a3, a4, 1268; RV32I-NEXT: j .LBB1_1069; RV32I-NEXT: .LBB1_9:70; RV32I-NEXT: addi a3, a3, 1271; RV32I-NEXT: .LBB1_10: # %entry72; RV32I-NEXT: lw a1, 0(a3)73; RV32I-NEXT: sw a2, 0(a0)74; RV32I-NEXT: sw a5, 4(a0)75; RV32I-NEXT: sw a6, 8(a0)76; RV32I-NEXT: sw a1, 12(a0)77; RV32I-NEXT: ret78;79; RV64I-LABEL: cmovcc128:80; RV64I: # %bb.0: # %entry81; RV64I-NEXT: li a5, 12382; RV64I-NEXT: beq a0, a5, .LBB1_283; RV64I-NEXT: # %bb.1: # %entry84; RV64I-NEXT: mv a1, a385; RV64I-NEXT: mv a2, a486; RV64I-NEXT: .LBB1_2: # %entry87; RV64I-NEXT: mv a0, a188; RV64I-NEXT: mv a1, a289; RV64I-NEXT: ret90entry:91 %cmp = icmp eq i64 %a, 12392 %cond = select i1 %cmp, i128 %b, i128 %c93 ret i128 %cond94}95 96define i64 @cmov64(i1 %a, i64 %b, i64 %c) nounwind {97; RV32I-LABEL: cmov64:98; RV32I: # %bb.0: # %entry99; RV32I-NEXT: andi a5, a0, 1100; RV32I-NEXT: mv a0, a1101; RV32I-NEXT: bnez a5, .LBB2_2102; RV32I-NEXT: # %bb.1: # %entry103; RV32I-NEXT: mv a0, a3104; RV32I-NEXT: mv a2, a4105; RV32I-NEXT: .LBB2_2: # %entry106; RV32I-NEXT: mv a1, a2107; RV32I-NEXT: ret108;109; RV64I-LABEL: cmov64:110; RV64I: # %bb.0: # %entry111; RV64I-NEXT: andi a3, a0, 1112; RV64I-NEXT: mv a0, a1113; RV64I-NEXT: bnez a3, .LBB2_2114; RV64I-NEXT: # %bb.1: # %entry115; RV64I-NEXT: mv a0, a2116; RV64I-NEXT: .LBB2_2: # %entry117; RV64I-NEXT: ret118entry:119 %cond = select i1 %a, i64 %b, i64 %c120 ret i64 %cond121}122 123define i128 @cmov128(i1 %a, i128 %b, i128 %c) nounwind {124; RV32I-LABEL: cmov128:125; RV32I: # %bb.0: # %entry126; RV32I-NEXT: andi a1, a1, 1127; RV32I-NEXT: mv a4, a2128; RV32I-NEXT: bnez a1, .LBB3_2129; RV32I-NEXT: # %bb.1: # %entry130; RV32I-NEXT: mv a4, a3131; RV32I-NEXT: .LBB3_2: # %entry132; RV32I-NEXT: bnez a1, .LBB3_5133; RV32I-NEXT: # %bb.3: # %entry134; RV32I-NEXT: addi a5, a3, 4135; RV32I-NEXT: beqz a1, .LBB3_6136; RV32I-NEXT: .LBB3_4:137; RV32I-NEXT: addi a6, a2, 8138; RV32I-NEXT: j .LBB3_7139; RV32I-NEXT: .LBB3_5:140; RV32I-NEXT: addi a5, a2, 4141; RV32I-NEXT: bnez a1, .LBB3_4142; RV32I-NEXT: .LBB3_6: # %entry143; RV32I-NEXT: addi a6, a3, 8144; RV32I-NEXT: .LBB3_7: # %entry145; RV32I-NEXT: lw a4, 0(a4)146; RV32I-NEXT: lw a5, 0(a5)147; RV32I-NEXT: lw a6, 0(a6)148; RV32I-NEXT: bnez a1, .LBB3_9149; RV32I-NEXT: # %bb.8: # %entry150; RV32I-NEXT: addi a2, a3, 12151; RV32I-NEXT: j .LBB3_10152; RV32I-NEXT: .LBB3_9:153; RV32I-NEXT: addi a2, a2, 12154; RV32I-NEXT: .LBB3_10: # %entry155; RV32I-NEXT: lw a1, 0(a2)156; RV32I-NEXT: sw a4, 0(a0)157; RV32I-NEXT: sw a5, 4(a0)158; RV32I-NEXT: sw a6, 8(a0)159; RV32I-NEXT: sw a1, 12(a0)160; RV32I-NEXT: ret161;162; RV64I-LABEL: cmov128:163; RV64I: # %bb.0: # %entry164; RV64I-NEXT: andi a5, a0, 1165; RV64I-NEXT: mv a0, a1166; RV64I-NEXT: bnez a5, .LBB3_2167; RV64I-NEXT: # %bb.1: # %entry168; RV64I-NEXT: mv a0, a3169; RV64I-NEXT: mv a2, a4170; RV64I-NEXT: .LBB3_2: # %entry171; RV64I-NEXT: mv a1, a2172; RV64I-NEXT: ret173entry:174 %cond = select i1 %a, i128 %b, i128 %c175 ret i128 %cond176}177 178define float @cmovfloat(i1 %a, float %b, float %c, float %d, float %e) nounwind {179; RV32I-LABEL: cmovfloat:180; RV32I: # %bb.0: # %entry181; RV32I-NEXT: andi a0, a0, 1182; RV32I-NEXT: bnez a0, .LBB4_2183; RV32I-NEXT: # %bb.1: # %entry184; RV32I-NEXT: fmv.w.x fa5, a4185; RV32I-NEXT: fmv.w.x fa4, a2186; RV32I-NEXT: j .LBB4_3187; RV32I-NEXT: .LBB4_2:188; RV32I-NEXT: fmv.w.x fa5, a3189; RV32I-NEXT: fmv.w.x fa4, a1190; RV32I-NEXT: .LBB4_3: # %entry191; RV32I-NEXT: fadd.s fa5, fa4, fa5192; RV32I-NEXT: fmv.x.w a0, fa5193; RV32I-NEXT: ret194;195; RV64I-LABEL: cmovfloat:196; RV64I: # %bb.0: # %entry197; RV64I-NEXT: andi a0, a0, 1198; RV64I-NEXT: bnez a0, .LBB4_2199; RV64I-NEXT: # %bb.1: # %entry200; RV64I-NEXT: fmv.w.x fa5, a4201; RV64I-NEXT: fmv.w.x fa4, a2202; RV64I-NEXT: j .LBB4_3203; RV64I-NEXT: .LBB4_2:204; RV64I-NEXT: fmv.w.x fa5, a3205; RV64I-NEXT: fmv.w.x fa4, a1206; RV64I-NEXT: .LBB4_3: # %entry207; RV64I-NEXT: fadd.s fa5, fa4, fa5208; RV64I-NEXT: fmv.x.w a0, fa5209; RV64I-NEXT: ret210entry:211 %cond1 = select i1 %a, float %b, float %c212 %cond2 = select i1 %a, float %d, float %e213 %ret = fadd float %cond1, %cond2214 ret float %ret215}216 217define double @cmovdouble(i1 %a, double %b, double %c) nounwind {218; RV32I-LABEL: cmovdouble:219; RV32I: # %bb.0: # %entry220; RV32I-NEXT: addi sp, sp, -16221; RV32I-NEXT: sw a3, 8(sp)222; RV32I-NEXT: sw a4, 12(sp)223; RV32I-NEXT: fld fa5, 8(sp)224; RV32I-NEXT: andi a0, a0, 1225; RV32I-NEXT: sw a1, 8(sp)226; RV32I-NEXT: sw a2, 12(sp)227; RV32I-NEXT: beqz a0, .LBB5_2228; RV32I-NEXT: # %bb.1:229; RV32I-NEXT: fld fa5, 8(sp)230; RV32I-NEXT: .LBB5_2: # %entry231; RV32I-NEXT: fsd fa5, 8(sp)232; RV32I-NEXT: lw a0, 8(sp)233; RV32I-NEXT: lw a1, 12(sp)234; RV32I-NEXT: addi sp, sp, 16235; RV32I-NEXT: ret236;237; RV64I-LABEL: cmovdouble:238; RV64I: # %bb.0: # %entry239; RV64I-NEXT: andi a0, a0, 1240; RV64I-NEXT: bnez a0, .LBB5_2241; RV64I-NEXT: # %bb.1: # %entry242; RV64I-NEXT: fmv.d.x fa5, a2243; RV64I-NEXT: fmv.x.d a0, fa5244; RV64I-NEXT: ret245; RV64I-NEXT: .LBB5_2:246; RV64I-NEXT: fmv.d.x fa5, a1247; RV64I-NEXT: fmv.x.d a0, fa5248; RV64I-NEXT: ret249entry:250 %cond = select i1 %a, double %b, double %c251 ret double %cond252}253 254; Check that selects with dependencies on previous ones aren't incorrectly255; optimized.256 257define i32 @cmovccdep(i32 signext %a, i32 %b, i32 %c, i32 %d) nounwind {258; RV32I-LABEL: cmovccdep:259; RV32I: # %bb.0: # %entry260; RV32I-NEXT: li a4, 123261; RV32I-NEXT: bne a0, a4, .LBB6_3262; RV32I-NEXT: # %bb.1: # %entry263; RV32I-NEXT: mv a2, a1264; RV32I-NEXT: bne a0, a4, .LBB6_4265; RV32I-NEXT: .LBB6_2: # %entry266; RV32I-NEXT: add a0, a1, a2267; RV32I-NEXT: ret268; RV32I-NEXT: .LBB6_3: # %entry269; RV32I-NEXT: mv a1, a2270; RV32I-NEXT: beq a0, a4, .LBB6_2271; RV32I-NEXT: .LBB6_4: # %entry272; RV32I-NEXT: add a0, a1, a3273; RV32I-NEXT: ret274;275; RV64I-LABEL: cmovccdep:276; RV64I: # %bb.0: # %entry277; RV64I-NEXT: li a4, 123278; RV64I-NEXT: bne a0, a4, .LBB6_3279; RV64I-NEXT: # %bb.1: # %entry280; RV64I-NEXT: mv a2, a1281; RV64I-NEXT: bne a0, a4, .LBB6_4282; RV64I-NEXT: .LBB6_2: # %entry283; RV64I-NEXT: addw a0, a1, a2284; RV64I-NEXT: ret285; RV64I-NEXT: .LBB6_3: # %entry286; RV64I-NEXT: mv a1, a2287; RV64I-NEXT: beq a0, a4, .LBB6_2288; RV64I-NEXT: .LBB6_4: # %entry289; RV64I-NEXT: addw a0, a1, a3290; RV64I-NEXT: ret291entry:292 %cmp = icmp eq i32 %a, 123293 %cond1 = select i1 %cmp, i32 %b, i32 %c294 %cond2 = select i1 %cmp, i32 %cond1, i32 %d295 %ret = add i32 %cond1, %cond2296 ret i32 %ret297}298 299; Check that selects with different conditions aren't incorrectly optimized.300 301define i32 @cmovdiffcc(i1 %a, i1 %b, i32 %c, i32 %d, i32 %e, i32 %f) nounwind {302; RV32I-LABEL: cmovdiffcc:303; RV32I: # %bb.0: # %entry304; RV32I-NEXT: andi a0, a0, 1305; RV32I-NEXT: andi a1, a1, 1306; RV32I-NEXT: beqz a0, .LBB7_3307; RV32I-NEXT: # %bb.1: # %entry308; RV32I-NEXT: beqz a1, .LBB7_4309; RV32I-NEXT: .LBB7_2: # %entry310; RV32I-NEXT: add a0, a2, a4311; RV32I-NEXT: ret312; RV32I-NEXT: .LBB7_3: # %entry313; RV32I-NEXT: mv a2, a3314; RV32I-NEXT: bnez a1, .LBB7_2315; RV32I-NEXT: .LBB7_4: # %entry316; RV32I-NEXT: add a0, a2, a5317; RV32I-NEXT: ret318;319; RV64I-LABEL: cmovdiffcc:320; RV64I: # %bb.0: # %entry321; RV64I-NEXT: andi a0, a0, 1322; RV64I-NEXT: andi a1, a1, 1323; RV64I-NEXT: beqz a0, .LBB7_3324; RV64I-NEXT: # %bb.1: # %entry325; RV64I-NEXT: beqz a1, .LBB7_4326; RV64I-NEXT: .LBB7_2: # %entry327; RV64I-NEXT: addw a0, a2, a4328; RV64I-NEXT: ret329; RV64I-NEXT: .LBB7_3: # %entry330; RV64I-NEXT: mv a2, a3331; RV64I-NEXT: bnez a1, .LBB7_2332; RV64I-NEXT: .LBB7_4: # %entry333; RV64I-NEXT: addw a0, a2, a5334; RV64I-NEXT: ret335entry:336 %cond1 = select i1 %a, i32 %c, i32 %d337 %cond2 = select i1 %b, i32 %e, i32 %f338 %ret = add i32 %cond1, %cond2339 ret i32 %ret340}341