diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -182,12 +182,18 @@ MachineBasicBlock &MBB = *MI.getParent(); bool FrameRegIsKill = false; + // If the instruction is an ADDI, we can use it's destination as a scratch + // register. Load instructions might have an FP or vector destination and + // stores don't have a destination register. + Register DestReg; + if (MI.getOpcode() == RISCV::ADDI) + DestReg = MI.getOperand(0).getReg(); + // If required, pre-compute the scalable factor amount which will be used in // later offset computation. Since this sequence requires up to two scratch // registers -- after which one is made free -- this grants us better // scavenging of scratch registers as only up to two are live at one time, // rather than three. - Register ScalableFactorRegister; unsigned ScalableAdjOpc = RISCV::ADD; if (Offset.getScalable()) { int64_t ScalableValue = Offset.getScalable(); @@ -195,55 +201,58 @@ ScalableValue = -ScalableValue; ScalableAdjOpc = RISCV::SUB; } - // 1. Get vlenb && multiply vlen with the number of vector registers. - ScalableFactorRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass); - TII->getVLENFactoredAmount(MF, MBB, II, DL, ScalableFactorRegister, - ScalableValue); + // Use DestReg if it exists, otherwise create a new register. + if (!DestReg) + DestReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + // Get vlenb && multiply vlen with the number of vector registers. + TII->getVLENFactoredAmount(MF, MBB, II, DL, DestReg, ScalableValue); } if (!isInt<12>(Offset.getFixed())) { // The offset won't fit in an immediate, so use a scratch register instead - // Modify Offset and FrameReg appropriately - Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + // Modify Offset and FrameReg appropriately. + + // Reuse destination register if it exists and is not holding a scalable + // offset. + Register ScratchReg = DestReg; + if (!DestReg || Offset.getScalable()) { + ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + // Also save to DestReg if it doesn't exist. + if (!DestReg) + DestReg = ScratchReg; + } + TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed()); - if (MI.getOpcode() == RISCV::ADDI && !Offset.getScalable()) { - BuildMI(MBB, II, DL, TII->get(RISCV::ADD), MI.getOperand(0).getReg()) - .addReg(FrameReg) + BuildMI(MBB, II, DL, TII->get(RISCV::ADD), ScratchReg) + .addReg(FrameReg, getKillRegState(FrameRegIsKill)) .addReg(ScratchReg, RegState::Kill); + // If this was an ADDI and there is no scalable offset, we can remove it. + if (MI.getOpcode() == RISCV::ADDI && !Offset.getScalable()) { + assert(MI.getOperand(0).getReg() == ScratchReg && + "Expected to have written ADDI destination register"); MI.eraseFromParent(); return; } - BuildMI(MBB, II, DL, TII->get(RISCV::ADD), ScratchReg) - .addReg(FrameReg) - .addReg(ScratchReg, RegState::Kill); + Offset = StackOffset::get(0, Offset.getScalable()); FrameReg = ScratchReg; FrameRegIsKill = true; } - Register ScratchReg; - - // Add in the scalable offset which has already been computed in - // ScalableFactorRegister. + // Add in the scalable offset which has already been computed in DestReg. if (Offset.getScalable()) { - assert(ScalableFactorRegister && - "Expected pre-computation of scalable factor in earlier step"); - - // Calculate address: FrameReg + ScalableFactorRegister. + assert(DestReg && "DestReg should be valid"); + BuildMI(MBB, II, DL, TII->get(ScalableAdjOpc), DestReg) + .addReg(FrameReg, getKillRegState(FrameRegIsKill)) + .addReg(DestReg, RegState::Kill); + // If this was an ADDI and there is no fixed offset, we can remove it. if (MI.getOpcode() == RISCV::ADDI && !Offset.getFixed()) { - BuildMI(MBB, II, DL, TII->get(ScalableAdjOpc), MI.getOperand(0).getReg()) - .addReg(FrameReg, getKillRegState(FrameRegIsKill)) - .addReg(ScalableFactorRegister, RegState::Kill); + assert(MI.getOperand(0).getReg() == DestReg && + "Expected to have written ADDI destination register"); MI.eraseFromParent(); return; } - - assert(!ScratchReg && "Already populated ScratchReg?"); - ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); - BuildMI(MBB, II, DL, TII->get(ScalableAdjOpc), ScratchReg) - .addReg(FrameReg, getKillRegState(FrameRegIsKill)) - .addReg(ScalableFactorRegister, RegState::Kill); - FrameReg = ScratchReg; + FrameReg = DestReg; FrameRegIsKill = true; } @@ -252,13 +261,13 @@ // RVVSpills don't have an immediate. Add an ADDI if the fixed offset is // needed. if (Offset.getFixed()) { - // Reuse ScratchReg if it exists, otherwise create a new register. - if (!ScratchReg) - ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); - BuildMI(MBB, II, DL, TII->get(RISCV::ADDI), ScratchReg) + // Reuse DestReg if it exists, otherwise create a new register. + if (!DestReg) + DestReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + BuildMI(MBB, II, DL, TII->get(RISCV::ADDI), DestReg) .addReg(FrameReg, getKillRegState(FrameRegIsKill)) .addImm(Offset.getFixed()); - FrameReg = ScratchReg; + FrameReg = DestReg; FrameRegIsKill = true; } } else { diff --git a/llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir b/llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir --- a/llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir +++ b/llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir @@ -42,12 +42,12 @@ ; CHECK-NEXT: $x2 = frame-setup SUB $x2, killed $x12 ; CHECK-NEXT: dead $x0 = PseudoVSETVLI killed renamable $x11, 88 /* e64, m1, ta, mu */, implicit-def $vl, implicit-def $vtype ; CHECK-NEXT: renamable $v8 = PseudoVLE64_V_M1 killed renamable $x10, $noreg, 6 /* e64 */, implicit $vl, implicit $vtype :: (load unknown-size from %ir.pa, align 8) - ; CHECK-NEXT: $x11 = PseudoReadVLENB - ; CHECK-NEXT: $x11 = SLLI killed $x11, 1 - ; CHECK-NEXT: $x10 = LUI 1048575 - ; CHECK-NEXT: $x10 = ADDIW killed $x10, 1824 - ; CHECK-NEXT: $x10 = ADD $x8, killed $x10 - ; CHECK-NEXT: $x10 = SUB killed $x10, killed $x11 + ; CHECK-NEXT: $x10 = PseudoReadVLENB + ; CHECK-NEXT: $x10 = SLLI killed $x10, 1 + ; CHECK-NEXT: $x11 = LUI 1048575 + ; CHECK-NEXT: $x11 = ADDIW killed $x11, 1824 + ; CHECK-NEXT: $x11 = ADD $x8, killed $x11 + ; CHECK-NEXT: $x10 = SUB killed $x11, killed $x10 ; CHECK-NEXT: VS1R_V killed renamable $v8, killed renamable $x10 ; CHECK-NEXT: $x2 = frame-destroy ADDI $x8, -2048 ; CHECK-NEXT: $x2 = frame-destroy ADDI killed $x2, -224 diff --git a/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll @@ -537,10 +537,10 @@ ; RV32-NEXT: li a5, 5 ; RV32-NEXT: li a6, 6 ; RV32-NEXT: li a7, 7 -; RV32-NEXT: csrr t0, vlenb -; RV32-NEXT: slli t0, t0, 4 -; RV32-NEXT: add t0, sp, t0 -; RV32-NEXT: addi t2, t0, 128 +; RV32-NEXT: csrr t2, vlenb +; RV32-NEXT: slli t2, t2, 4 +; RV32-NEXT: add t2, sp, t2 +; RV32-NEXT: addi t2, t2, 128 ; RV32-NEXT: addi t4, sp, 128 ; RV32-NEXT: li t6, 8 ; RV32-NEXT: vs8r.v v8, (a0) @@ -585,10 +585,10 @@ ; RV64-NEXT: li a5, 5 ; RV64-NEXT: li a6, 6 ; RV64-NEXT: li a7, 7 -; RV64-NEXT: csrr t0, vlenb -; RV64-NEXT: slli t0, t0, 4 -; RV64-NEXT: add t0, sp, t0 -; RV64-NEXT: addi t2, t0, 128 +; RV64-NEXT: csrr t2, vlenb +; RV64-NEXT: slli t2, t2, 4 +; RV64-NEXT: add t2, sp, t2 +; RV64-NEXT: addi t2, t2, 128 ; RV64-NEXT: addi t4, sp, 128 ; RV64-NEXT: li t6, 8 ; RV64-NEXT: vs8r.v v8, (a0) diff --git a/llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir b/llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir --- a/llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir +++ b/llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir @@ -89,13 +89,13 @@ ; CHECK-NEXT: $x2 = frame-setup ANDI $x2, -128 ; CHECK-NEXT: dead renamable $x15 = PseudoVSETIVLI 1, 72 /* e16, m1, ta, mu */, implicit-def $vl, implicit-def $vtype ; CHECK-NEXT: renamable $v25 = PseudoVMV_V_X_M1 killed renamable $x12, $noreg, 4 /* e16 */, implicit $vl, implicit $vtype - ; CHECK-NEXT: $x11 = PseudoReadVLENB - ; CHECK-NEXT: $x10 = ADDI killed $x0, 50 - ; CHECK-NEXT: $x11 = MUL killed $x11, killed $x10 - ; CHECK-NEXT: $x10 = LUI 1 - ; CHECK-NEXT: $x10 = ADDIW killed $x10, -1888 - ; CHECK-NEXT: $x10 = ADD $x2, killed $x10 - ; CHECK-NEXT: $x10 = ADD killed $x10, killed $x11 + ; CHECK-NEXT: $x10 = PseudoReadVLENB + ; CHECK-NEXT: $x11 = ADDI killed $x0, 50 + ; CHECK-NEXT: $x10 = MUL killed $x10, killed $x11 + ; CHECK-NEXT: $x11 = LUI 1 + ; CHECK-NEXT: $x11 = ADDIW killed $x11, -1888 + ; CHECK-NEXT: $x11 = ADD $x2, killed $x11 + ; CHECK-NEXT: $x10 = ADD killed $x11, killed $x10 ; CHECK-NEXT: PseudoVSPILL_M1 killed renamable $v25, killed $x10 :: (store unknown-size into %stack.1, align 8) ; CHECK-NEXT: renamable $x1 = ADDI $x0, 255 ; CHECK-NEXT: renamable $x5 = nuw ADDI $x2, 384 @@ -111,11 +111,9 @@ ; CHECK-NEXT: renamable $x21 = ADDI $x2, 1664 ; CHECK-NEXT: renamable $x22 = ADDI $x2, 1792 ; CHECK-NEXT: renamable $x23 = ADDI $x2, 1920 - ; CHECK-NEXT: SD killed $x1, $x2, 8 :: (store (s64) into %stack.15) - ; CHECK-NEXT: SD killed $x5, $x2, 0 :: (store (s64) into %stack.16) - ; CHECK-NEXT: $x11 = LUI 1 - ; CHECK-NEXT: $x11 = ADDIW killed $x11, -2048 - ; CHECK-NEXT: $x24 = ADD $x2, killed $x11 + ; CHECK-NEXT: $x24 = LUI 1 + ; CHECK-NEXT: $x24 = ADDIW killed $x24, -2048 + ; CHECK-NEXT: $x24 = ADD $x2, killed $x24 ; CHECK-NEXT: renamable $x25 = ADDI $x2, 128 ; CHECK-NEXT: renamable $x26 = ADDI $x2, 128 ; CHECK-NEXT: renamable $x27 = ADDI $x0, 2 @@ -131,16 +129,18 @@ ; CHECK-NEXT: renamable $x16 = SUB killed renamable $x13, renamable $x13 ; CHECK-NEXT: dead renamable $x13 = PseudoVSETIVLI 1, 64 /* e8, m1, ta, mu */, implicit-def $vl, implicit-def $vtype ; CHECK-NEXT: renamable $x13 = nsw ADDI renamable $x16, -2 - ; CHECK-NEXT: $x5 = PseudoReadVLENB - ; CHECK-NEXT: $x1 = ADDI killed $x0, 50 - ; CHECK-NEXT: $x5 = MUL killed $x5, killed $x1 - ; CHECK-NEXT: $x1 = LUI 1 - ; CHECK-NEXT: $x1 = ADDIW killed $x1, -1888 - ; CHECK-NEXT: $x1 = ADD $x2, killed $x1 - ; CHECK-NEXT: $x1 = ADD killed $x1, killed $x5 - ; CHECK-NEXT: $x5 = LD $x2, 0 :: (load (s64) from %stack.16) - ; CHECK-NEXT: renamable $v0 = PseudoVRELOAD_M1 killed $x1 :: (load unknown-size from %stack.1, align 8) - ; CHECK-NEXT: $x1 = LD $x2, 8 :: (load (s64) from %stack.15) + ; CHECK-NEXT: SD killed $x10, $x2, 8 :: (store (s64) into %stack.15) + ; CHECK-NEXT: $x10 = PseudoReadVLENB + ; CHECK-NEXT: SD killed $x12, $x2, 0 :: (store (s64) into %stack.16) + ; CHECK-NEXT: $x12 = ADDI killed $x0, 50 + ; CHECK-NEXT: $x10 = MUL killed $x10, killed $x12 + ; CHECK-NEXT: $x12 = LUI 1 + ; CHECK-NEXT: $x12 = ADDIW killed $x12, -1888 + ; CHECK-NEXT: $x12 = ADD $x2, killed $x12 + ; CHECK-NEXT: $x10 = ADD killed $x12, killed $x10 + ; CHECK-NEXT: $x12 = LD $x2, 0 :: (load (s64) from %stack.16) + ; CHECK-NEXT: renamable $v0 = PseudoVRELOAD_M1 killed $x10 :: (load unknown-size from %stack.1, align 8) + ; CHECK-NEXT: $x10 = LD $x2, 8 :: (load (s64) from %stack.15) ; CHECK-NEXT: renamable $v0 = PseudoVSLIDEDOWN_VX_M1 undef renamable $v0, killed renamable $v0, killed renamable $x13, $noreg, 3 /* e8 */, 1 /* ta, mu */, implicit $vl, implicit $vtype ; CHECK-NEXT: renamable $x13 = PseudoVMV_X_S_M1 killed renamable $v0, 3 /* e8 */, implicit $vl, implicit $vtype ; CHECK-NEXT: BLT killed renamable $x16, renamable $x27, %bb.2 diff --git a/llvm/test/CodeGen/RISCV/rvv/localvar.ll b/llvm/test/CodeGen/RISCV/rvv/localvar.ll --- a/llvm/test/CodeGen/RISCV/rvv/localvar.ll +++ b/llvm/test/CodeGen/RISCV/rvv/localvar.ll @@ -207,10 +207,10 @@ ; RV64IV-NEXT: slli a1, a1, 1 ; RV64IV-NEXT: sub a1, s0, a1 ; RV64IV-NEXT: addi a1, a1, -32 -; RV64IV-NEXT: csrr a2, vlenb -; RV64IV-NEXT: slli a2, a2, 1 -; RV64IV-NEXT: sub a2, s0, a2 -; RV64IV-NEXT: addi s1, a2, -32 +; RV64IV-NEXT: csrr s1, vlenb +; RV64IV-NEXT: slli s1, s1, 1 +; RV64IV-NEXT: sub s1, s0, s1 +; RV64IV-NEXT: addi s1, s1, -32 ; RV64IV-NEXT: call notdead@plt ; RV64IV-NEXT: vl2r.v v8, (s1) ; RV64IV-NEXT: csrr a0, vlenb @@ -262,10 +262,10 @@ ; RV64IV-NEXT: slli a2, a2, 1 ; RV64IV-NEXT: add a2, s1, a2 ; RV64IV-NEXT: addi a2, a2, 224 -; RV64IV-NEXT: csrr a3, vlenb -; RV64IV-NEXT: slli a3, a3, 1 -; RV64IV-NEXT: add a3, s1, a3 -; RV64IV-NEXT: addi s2, a3, 224 +; RV64IV-NEXT: csrr s2, vlenb +; RV64IV-NEXT: slli s2, s2, 1 +; RV64IV-NEXT: add s2, s1, s2 +; RV64IV-NEXT: addi s2, s2, 224 ; RV64IV-NEXT: call notdead2@plt ; RV64IV-NEXT: lw a0, 124(s1) ; RV64IV-NEXT: vl2r.v v8, (s2) diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-out-arguments.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-out-arguments.ll --- a/llvm/test/CodeGen/RISCV/rvv/rvv-out-arguments.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-out-arguments.ll @@ -80,10 +80,10 @@ ; CHECK-NEXT: addi a1, s0, -56 ; CHECK-NEXT: vsetvli zero, a0, e32, m8, ta, mu ; CHECK-NEXT: vle32.v v8, (a1) -; CHECK-NEXT: csrr a0, vlenb -; CHECK-NEXT: slli a0, a0, 3 -; CHECK-NEXT: sub a0, s0, a0 -; CHECK-NEXT: addi s1, a0, -112 +; CHECK-NEXT: csrr s1, vlenb +; CHECK-NEXT: slli s1, s1, 3 +; CHECK-NEXT: sub s1, s0, s1 +; CHECK-NEXT: addi s1, s1, -112 ; CHECK-NEXT: vs8r.v v8, (s1) ; CHECK-NEXT: li a0, 1 ; CHECK-NEXT: sw a0, -68(s0)