diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp --- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -715,20 +715,60 @@ insertVSETVLI(MBB, MachineBasicBlock::iterator(&MI), DL, Info, PrevInfo); } +// Return a VSETVLIInfo representing the changes made by this VSETVLI or +// VSETIVLI instruction. +static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) { + VSETVLIInfo NewInfo; + if (MI.getOpcode() == RISCV::PseudoVSETIVLI) { + NewInfo.setAVLImm(MI.getOperand(1).getImm()); + } else { + assert(MI.getOpcode() == RISCV::PseudoVSETVLI || + MI.getOpcode() == RISCV::PseudoVSETVLIX0); + Register AVLReg = MI.getOperand(1).getReg(); + assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) && + "Can't handle X0, X0 vsetvli yet"); + NewInfo.setAVLReg(AVLReg); + } + NewInfo.setVTYPE(MI.getOperand(2).getImm()); + + return NewInfo; +} + void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertPt, DebugLoc DL, const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo) { - // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same - // VLMAX. - if (PrevInfo.isValid() && !PrevInfo.isUnknown() && - Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addReg(RISCV::X0, RegState::Kill) - .addImm(Info.encodeVTYPE()) - .addReg(RISCV::VL, RegState::Implicit); - return; + if (PrevInfo.isValid() && !PrevInfo.isUnknown()) { + // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same + // VLMAX. + if (Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { + BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()) + .addReg(RISCV::VL, RegState::Implicit); + return; + } + + // If our AVL is a virtual register, it might be defined by a VSET(I)VLI. If + // it has the same VLMAX we want and the last VL/VTYPE we observed is the + // same, we can use the X0, X0 form. + if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg() && + Info.getAVLReg().isVirtual()) { + if (MachineInstr *DefMI = MRI->getVRegDef(Info.getAVLReg())) { + if (isVectorConfigInstr(*DefMI)) { + VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); + if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) { + BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()) + .addReg(RISCV::VL, RegState::Implicit); + return; + } + } + } + } } if (Info.hasAVLImm()) { @@ -778,25 +818,6 @@ .addImm(Info.encodeVTYPE()); } -// Return a VSETVLIInfo representing the changes made by this VSETVLI or -// VSETIVLI instruction. -static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) { - VSETVLIInfo NewInfo; - if (MI.getOpcode() == RISCV::PseudoVSETIVLI) { - NewInfo.setAVLImm(MI.getOperand(1).getImm()); - } else { - assert(MI.getOpcode() == RISCV::PseudoVSETVLI || - MI.getOpcode() == RISCV::PseudoVSETVLIX0); - Register AVLReg = MI.getOperand(1).getReg(); - assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) && - "Can't handle X0, X0 vsetvli yet"); - NewInfo.setAVLReg(AVLReg); - } - NewInfo.setVTYPE(MI.getOperand(2).getImm()); - - return NewInfo; -} - /// Return true if a VSETVLI is required to transition from CurInfo to Require /// before MI. bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI, diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll @@ -18,7 +18,6 @@ define @test1(i64 %avl, %a, %b) nounwind { ; CHECK-LABEL: test1: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli a0, a0, e32, mf2, ta, ma ; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma ; CHECK-NEXT: vfadd.vv v8, v8, v9 ; CHECK-NEXT: ret @@ -51,7 +50,6 @@ define @test3(i64 %avl, %a, * %b, %c) nounwind { ; CHECK-LABEL: test3: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli a0, a0, e64, m1, ta, ma ; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, mu ; CHECK-NEXT: vle64.v v8, (a1), v0.t ; CHECK-NEXT: ret @@ -560,9 +558,9 @@ define @test20(i64 %avl, %a, %b, %c) nounwind { ; CHECK-LABEL: test20: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli a0, a0, e32, mf2, ta, ma +; CHECK-NEXT: vsetvli zero, a0, e32, mf2, ta, ma ; CHECK-NEXT: vfwadd.vv v11, v8, v9 -; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma ; CHECK-NEXT: vfadd.vv v8, v11, v10 ; CHECK-NEXT: ret entry: