This testcase show the live range isn't construct correctly when subreg
liveness is enabled.
In the testcase early-clobber-tied-def-subreg-liveness.ll, first operand of
vsext.vf2 v8, v16, v0.t is both def and use, and the use is come from
the memory location of .L__const._Z3foov.var_49, it's load and spilled
into stack, and then...v8 is overwrite by another instructions.
lui a0, %hi(.L__const._Z3foov.var_49) addi a0, a0, %lo(.L__const._Z3foov.var_49) ... vle16.v v8, (a0) # Load value from var_49 ... addi a0, sp, 16 ... vs2r.v v8, (a0) # Spill ... vl2r.v v8, (a1) # Reload ... lui a0, %hi(.L__const._Z3foov.var_40) addi a0, a0, %lo(.L__const._Z3foov.var_40) vle16.v v8, (a0) # Load value...into v8??? vmsbc.vx v0, v8, a0 # And use that. ... vsext.vf2 v8, v16, v0.t # But v8 is here...which is expect value from the reload
The early-clobber-tied-def-subreg-liveness.mir has more detailed
infomation for that, %25.sub_vrm2_0 is defined in 64, and used in 464,
and defined again in 464, and we has used an inline asm to clobber all
vector register for trigger spliter.
0B bb.0.entry: 16B %0:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_49 32B %1:gpr = ADDI %0:gpr, target-flags(riscv-lo) @__const._Z3foov.var_49 48B dead $x0 = PseudoVSETIVLI 2, 73, implicit-def $vl, implicit-def $vtype 64B undef %25.sub_vrm2_0:vrn4m2nov0 = PseudoVLE16_V_M2 %1:gpr, 2, 4, implicit $vl, implicit $vtype 80B %3:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_48 96B %4:gpr = ADDI %3:gpr, target-flags(riscv-lo) @__const._Z3foov.var_48 112B %5:vr = PseudoVLE8_V_M1 %4:gpr, 2, 3, implicit $vl, implicit $vtype 128B %6:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_46 144B %7:gpr = ADDI %6:gpr, target-flags(riscv-lo) @__const._Z3foov.var_46 160B %25.sub_vrm2_1:vrn4m2nov0 = PseudoVLE16_V_M2 %7:gpr, 2, 4, implicit $vl, implicit $vtype 176B %9:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_45 192B %10:gpr = ADDI %9:gpr, target-flags(riscv-lo) @__const._Z3foov.var_45 208B %25.sub_vrm2_2:vrn4m2nov0 = PseudoVLE16_V_M2 %10:gpr, 2, 4, implicit $vl, implicit $vtype 224B INLINEASM &"" [sideeffect] [attdialect], $0:[clobber], ... 240B %12:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_44 256B %13:gpr = ADDI %12:gpr, target-flags(riscv-lo) @__const._Z3foov.var_44 272B dead $x0 = PseudoVSETIVLI 2, 73, implicit-def $vl, implicit-def $vtype 288B %25.sub_vrm2_3:vrn4m2nov0 = PseudoVLE16_V_M2 %13:gpr, 2, 4, implicit $vl, implicit $vtype 304B $x0 = PseudoVSETIVLI 2, 73, implicit-def $vl, implicit-def $vtype 320B %16:gpr = LUI target-flags(riscv-hi) @__const._Z3foov.var_40 336B %17:gpr = ADDI %16:gpr, target-flags(riscv-lo) @__const._Z3foov.var_40 352B %18:vrm2 = PseudoVLE16_V_M2 %17:gpr, 2, 4, implicit $vl, implicit $vtype 368B $x0 = PseudoVSETIVLI 2, 73, implicit-def $vl, implicit-def $vtype 384B %20:gpr = LUI 1048572 400B %21:gpr = ADDIW %20:gpr, 928 416B early-clobber %22:vr = PseudoVMSBC_VX_M2 %18:vrm2, %21:gpr, 2, 4, implicit $vl, implicit $vtype 432B $x0 = PseudoVSETIVLI 2, 9, implicit-def $vl, implicit-def $vtype 448B $v0 = COPY %22:vr 464B early-clobber %25.sub_vrm2_0:vrn4m2nov0 = PseudoVSEXT_VF2_M2_MASK %25.sub_vrm2_0:vrn4m2nov0(tied-def 0), %5:vr, killed $v0, 2, 4, 0, implicit $vl, implicit $vtype 480B %26:gpr = LUI target-flags(riscv-hi) @var_47 496B %27:gpr = ADDI %26:gpr, target-flags(riscv-lo) @var_47 512B PseudoVSSEG4E16_V_M2 %25:vrn4m2nov0, %27:gpr, 2, 4, implicit $vl, implicit $vtype 528B PseudoRET
When spliter will try to split %25:
selectOrSplit VRN4M2NoV0:%25 [64r,160r:4)[160r,208r:0)[208r,288r:1)[288r,464e:2)[464e,512r:3) 0@160r 1@208r 2@288r 3@464e 4@64r L0000000000000030 [160r,512r:0) 0@160r L00000000000000C0 [208r,512r:0) 0@208r L0000000000000300 [288r,512r:0) 0@288r L000000000000000C [64r,464e:1)[464e,512r:0) 0@464e 1@64r weight:1.179245e-02 w=1.179245e-02
Best local split range: 64r-208r, 6.999861e-03, 3 instrs enterIntvBefore 64r: not live leaveIntvAfter 208r: valno 1 useIntv [64B;216r): [64B;216r):1 blit [64r,160r:4): [64r;160r)=1(%29)(recalc) blit [160r,208r:0): [160r;208r)=1(%29)(recalc) blit [208r,288r:1): [208r;216r)=1(%29)(recalc) [216r;288r)=0(%28)(recalc) blit [288r,464e:2): [288r;464e)=0(%28)(recalc) blit [464e,512r:3): [464e;512r)=0(%28)(recalc) rewr %bb.0 464e:0 early-clobber %28.sub_vrm2_0:vrn4m2nov0 = PseudoVSEXT_VF2_M2_MASK %25.sub_vrm2_0:vrn4m2nov0(tied-def 0), %5:vr, $v0, 2, 4, 0, implicit $vl, implicit $vtype rewr %bb.0 288r:0 %28.sub_vrm2_3:vrn4m2nov0 = PseudoVLE16_V_M2 %13:gpr, 2, 4, implicit $vl, implicit $vtype rewr %bb.0 208r:1 %29.sub_vrm2_2:vrn4m2nov0 = PseudoVLE16_V_M2 %10:gpr, 2, 4, implicit $vl, implicit $vtype rewr %bb.0 160r:1 %29.sub_vrm2_1:vrn4m2nov0 = PseudoVLE16_V_M2 %7:gpr, 2, 4, implicit $vl, implicit $vtype rewr %bb.0 64r:1 undef %29.sub_vrm2_0:vrn4m2nov0 = PseudoVLE16_V_M2 %1:gpr, 2, 4, implicit $vl, implicit $vtype rewr %bb.0 464B:0 early-clobber %28.sub_vrm2_0:vrn4m2nov0 = PseudoVSEXT_VF2_M2_MASK %28.sub_vrm2_0:vrn4m2nov0(tied-def 0), %5:vr, $v0, 2, 4, 0, implicit $vl, implicit $vtype rewr %bb.0 512B:0 PseudoVSSEG4E16_V_M2 %28:vrn4m2nov0, %27:gpr, 2, 4, implicit $vl, implicit $vtype rewr %bb.0 216B:1 undef %28.sub_vrm1_0_sub_vrm1_1_sub_vrm1_2_sub_vrm1_3_sub_vrm1_4_sub_vrm1_5:vrn4m2nov0 = COPY %29.sub_vrm1_0_sub_vrm1_1_sub_vrm1_2_sub_vrm1_3_sub_vrm1_4_sub_vrm1_5:vrn4m2nov0 queuing new interval: %28 [216r,288r:0)[288r,464e:1)[464e,512r:2) 0@216r 1@288r 2@464e L000000000000000C [216r,216d:0)[464e,512r:1) 0@216r 1@464e L0000000000000300 [288r,512r:0) 0@288r L00000000000000C0 [216r,512r:0) 0@216r L0000000000000030 [216r,512r:0) 0@216r weight:8.706897e-03 Enqueuing %28 queuing new interval: %29 [64r,160r:0)[160r,208r:1)[208r,216r:2) 0@64r 1@160r 2@208r L000000000000000C [64r,216r:0) 0@64r L00000000000000C0 [208r,216r:0) 0@208r L0000000000000030 [160r,216r:0) 0@160r weight:1.097826e-02 Enqueuing %29
The live range of first part subreg of %25 is become [216r,216d:0)[464e,512r:1),
however first live range should live until 464e rather than just live
and [216r,216d:0).
And then the register allocator allocated wrong result accroding the
live range info.