diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -105,6 +105,7 @@ case RISCV::PseudoLA_TLS_GD: return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); case RISCV::PseudoVSETVLI: + case RISCV::PseudoVSETVLIX0: case RISCV::PseudoVSETIVLI: return expandVSetVL(MBB, MBBI); case RISCV::PseudoVMCLR_M_B1: @@ -246,13 +247,14 @@ DebugLoc DL = MBBI->getDebugLoc(); assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI || + MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 || MBBI->getOpcode() == RISCV::PseudoVSETIVLI) && "Unexpected pseudo instruction"); unsigned Opcode; - if (MBBI->getOpcode() == RISCV::PseudoVSETVLI) - Opcode = RISCV::VSETVLI; - else + if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI) Opcode = RISCV::VSETIVLI; + else + Opcode = RISCV::VSETVLI; const MCInstrDesc &Desc = TII->get(Opcode); assert(Desc.getNumOperands() == 3 && "Unexpected instruction format"); diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -883,8 +883,10 @@ SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); SDValue VLOperand; + unsigned Opcode = RISCV::PseudoVSETVLI; if (VLMax) { VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT); + Opcode = RISCV::PseudoVSETVLIX0; } else { VLOperand = Node->getOperand(2); @@ -902,7 +904,7 @@ } ReplaceNode(Node, - CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, + CurDAG->getMachineNode(Opcode, DL, XLenVT, MVT::Other, VLOperand, VTypeIOp, /* Chain */ Node->getOperand(0))); return; 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 @@ -451,7 +451,7 @@ // VLMAX. if (PrevInfo.isValid() && !PrevInfo.isUnknown() && Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) + BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLIX0)) .addReg(RISCV::X0, RegState::Define | RegState::Dead) .addReg(RISCV::X0, RegState::Kill) .addImm(Info.encodeVTYPE()) @@ -473,7 +473,7 @@ // the previous vl to become invalid. if (PrevInfo.isValid() && !PrevInfo.isUnknown() && Info.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) + BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLIX0)) .addReg(RISCV::X0, RegState::Define | RegState::Dead) .addReg(RISCV::X0, RegState::Kill) .addImm(Info.encodeVTYPE()) @@ -488,11 +488,19 @@ return; } - // Use X0 as the DestReg unless AVLReg is X0. + if (AVLReg.isVirtual()) + MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass); + + // Use X0 as the DestReg unless AVLReg is X0. We also need to change the + // opcode if the AVLReg is X0 as they have different register classes for + // the AVL operand. Register DestReg = RISCV::X0; - if (AVLReg == RISCV::X0) + unsigned Opcode = RISCV::PseudoVSETVLI; + if (AVLReg == RISCV::X0) { DestReg = MRI->createVirtualRegister(&RISCV::GPRRegClass); - BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) + Opcode = RISCV::PseudoVSETVLIX0; + } + BuildMI(MBB, MI, DL, TII->get(Opcode)) .addReg(DestReg, RegState::Define | RegState::Dead) .addReg(AVLReg) .addImm(Info.encodeVTYPE()); @@ -502,14 +510,15 @@ // VSETIVLI instruction. static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) { VSETVLIInfo NewInfo; - if (MI.getOpcode() == RISCV::PseudoVSETVLI) { + 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); - } else { - assert(MI.getOpcode() == RISCV::PseudoVSETIVLI); - NewInfo.setAVLImm(MI.getOperand(1).getImm()); } NewInfo.setVTYPE(MI.getOperand(2).getImm()); @@ -530,6 +539,7 @@ Require.hasSameVTYPE(CurInfo)) { if (MachineInstr *DefMI = MRI->getVRegDef(Require.getAVLReg())) { if (DefMI->getOpcode() == RISCV::PseudoVSETVLI || + DefMI->getOpcode() == RISCV::PseudoVSETVLIX0 || DefMI->getOpcode() == RISCV::PseudoVSETIVLI) { VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVTYPE(CurInfo)) @@ -744,6 +754,7 @@ for (const MachineInstr &MI : MBB) { // If this is an explicit VSETVLI or VSETIVLI, update our state. if (MI.getOpcode() == RISCV::PseudoVSETVLI || + MI.getOpcode() == RISCV::PseudoVSETVLIX0 || MI.getOpcode() == RISCV::PseudoVSETIVLI) { HadVectorOp = true; BBInfo.Change = getInfoForVSETVLI(MI); @@ -855,6 +866,7 @@ // We need the PHI input to the be the output of a VSET(I)VLI. MachineInstr *DefMI = MRI->getVRegDef(InReg); if (!DefMI || (DefMI->getOpcode() != RISCV::PseudoVSETVLI && + DefMI->getOpcode() != RISCV::PseudoVSETVLIX0 && DefMI->getOpcode() != RISCV::PseudoVSETIVLI)) return true; @@ -879,6 +891,7 @@ for (MachineInstr &MI : MBB) { // If this is an explicit VSETVLI or VSETIVLI, update our state. if (MI.getOpcode() == RISCV::PseudoVSETVLI || + MI.getOpcode() == RISCV::PseudoVSETVLIX0 || MI.getOpcode() == RISCV::PseudoVSETIVLI) { // Conservatively, mark the VL and VTYPE as live. assert(MI.getOperand(3).getReg() == RISCV::VL && diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -3369,7 +3369,12 @@ // Pseudos. let hasSideEffects = 1, mayLoad = 0, mayStore = 0, Defs = [VL, VTYPE] in { -def PseudoVSETVLI : Pseudo<(outs GPR:$rd), (ins GPR:$rs1, VTypeIOp:$vtypei), []>; +// Due to rs1=X0 having special meaning, we need a GPRNoX0 register class for +// the when we aren't using one of the special X0 encodings. Otherwise it could +// be accidentally be made X0 by MachineIR optimizations. To satisfy the +// verifier, we also need a GPRX0 instruction for the special encodings. +def PseudoVSETVLI : Pseudo<(outs GPR:$rd), (ins GPRNoX0:$rs1, VTypeIOp:$vtypei), []>; +def PseudoVSETVLIX0 : Pseudo<(outs GPR:$rd), (ins GPRX0:$rs1, VTypeIOp:$vtypei), []>; def PseudoVSETIVLI : Pseudo<(outs GPR:$rd), (ins uimm5:$rs1, VTypeIOp:$vtypei), []>; } diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.mir b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.mir --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.mir +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.mir @@ -146,7 +146,7 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000) ; CHECK: liveins: $x10, $x11, $v8, $x12 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x12 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x12 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[COPY2:%[0-9]+]]:gpr = COPY $x11 ; CHECK: [[COPY3:%[0-9]+]]:gpr = COPY $x10 @@ -219,7 +219,7 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000) ; CHECK: liveins: $x10, $x11, $x12, $x13 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x13 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x13 ; CHECK: [[COPY1:%[0-9]+]]:gpr = COPY $x12 ; CHECK: [[COPY2:%[0-9]+]]:gpr = COPY $x11 ; CHECK: [[COPY3:%[0-9]+]]:gpr = COPY $x10 @@ -230,12 +230,12 @@ ; CHECK: PseudoBR %bb.1 ; CHECK: bb.1.if.then: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: dead $x0 = PseudoVSETVLI killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl + ; CHECK: dead $x0 = PseudoVSETVLIX0 killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl ; CHECK: early-clobber %1:vr = PseudoVZEXT_VF2_M1 [[PseudoVLE32_V_MF2_]], $noreg, 6, implicit $vl, implicit $vtype ; CHECK: PseudoBR %bb.3 ; CHECK: bb.2.if.else: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: dead $x0 = PseudoVSETVLI killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl + ; CHECK: dead $x0 = PseudoVSETVLIX0 killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl ; CHECK: early-clobber %2:vr = PseudoVSEXT_VF2_M1 [[PseudoVLE32_V_MF2_]], $noreg, 6, implicit $vl, implicit $vtype ; CHECK: bb.3.if.end: ; CHECK: [[PHI:%[0-9]+]]:vr = PHI %1, %bb.1, %2, %bb.2 @@ -294,7 +294,7 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000) ; CHECK: liveins: $x10, $v8, $v9, $x11 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x11 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x11 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v9 ; CHECK: [[COPY2:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[COPY3:%[0-9]+]]:gpr = COPY $x10 @@ -353,7 +353,7 @@ - { id: 4, class: gpr } - { id: 5, class: vr } - { id: 6, class: vr } - - { id: 7, class: gpr } + - { id: 7, class: gprnox0 } - { id: 8, class: gpr } liveins: - { reg: '$x10', virtual-reg: '%4' } @@ -368,7 +368,7 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000) ; CHECK: liveins: $x10, $v8, $v9, $x11 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x11 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x11 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v9 ; CHECK: [[COPY2:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[COPY3:%[0-9]+]]:gpr = COPY $x10 @@ -391,7 +391,7 @@ successors: %bb.2(0x30000000), %bb.1(0x50000000) liveins: $x10, $v8, $v9, $x11 - %7:gpr = COPY $x11 + %7:gprnox0 = COPY $x11 %6:vr = COPY $v9 %5:vr = COPY $v8 %4:gpr = COPY $x10 diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir @@ -113,7 +113,7 @@ ; CHECK-LABEL: name: add ; CHECK: liveins: $v8, $v9, $x10 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x10 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x10 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v9 ; CHECK: [[COPY2:%[0-9]+]]:vr = COPY $v8 ; CHECK: dead $x0 = PseudoVSETVLI [[COPY]], 88, implicit-def $vl, implicit-def $vtype @@ -151,7 +151,7 @@ ; CHECK-LABEL: name: load_add ; CHECK: liveins: $x10, $v8, $x11 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x11 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x11 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[COPY2:%[0-9]+]]:gpr = COPY $x10 ; CHECK: dead $x0 = PseudoVSETVLI [[COPY]], 88, implicit-def $vl, implicit-def $vtype @@ -189,11 +189,11 @@ ; CHECK-LABEL: name: load_zext ; CHECK: liveins: $x10, $x11 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x11 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x11 ; CHECK: [[COPY1:%[0-9]+]]:gpr = COPY $x10 ; CHECK: dead $x0 = PseudoVSETVLI [[COPY]], 87, implicit-def $vl, implicit-def $vtype ; CHECK: [[PseudoVLE32_V_MF2_:%[0-9]+]]:vr = PseudoVLE32_V_MF2 [[COPY1]], $noreg, 5, implicit $vl, implicit $vtype - ; CHECK: dead $x0 = PseudoVSETVLI killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl + ; CHECK: dead $x0 = PseudoVSETVLIX0 killed $x0, 88, implicit-def $vl, implicit-def $vtype, implicit $vl ; CHECK: early-clobber %3:vr = PseudoVZEXT_VF2_M1 killed [[PseudoVLE32_V_MF2_]], $noreg, 6, implicit $vl, implicit $vtype ; CHECK: $v8 = COPY %3 ; CHECK: PseudoRET implicit $v8 @@ -298,7 +298,7 @@ ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x10 ; CHECK: dead $x0 = PseudoVSETIVLI 2, 88, implicit-def $vl, implicit-def $vtype ; CHECK: [[PseudoVLE64_V_M1_:%[0-9]+]]:vr = PseudoVLE64_V_M1 [[COPY]], 2, 6, implicit $vl, implicit $vtype :: (load (s128) from %ir.x) - ; CHECK: dead %6:gpr = PseudoVSETVLI $x0, 88, implicit-def $vl, implicit-def $vtype + ; CHECK: dead %6:gpr = PseudoVSETVLIX0 $x0, 88, implicit-def $vl, implicit-def $vtype ; CHECK: [[PseudoVMV_V_I_M1_:%[0-9]+]]:vr = PseudoVMV_V_I_M1 0, $noreg, 6, implicit $vl, implicit $vtype ; CHECK: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF ; CHECK: dead $x0 = PseudoVSETIVLI 2, 88, implicit-def $vl, implicit-def $vtype @@ -323,7 +323,7 @@ registers: - { id: 0, class: vr } - { id: 1, class: vr } - - { id: 2, class: gpr } + - { id: 2, class: gprnox0 } - { id: 3, class: gpr } - { id: 4, class: vr } liveins: @@ -339,14 +339,14 @@ ; CHECK-LABEL: name: vsetvli_add ; CHECK: liveins: $v8, $v9, $x10 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x10 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x10 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v9 ; CHECK: [[COPY2:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[PseudoVSETVLI:%[0-9]+]]:gpr = PseudoVSETVLI [[COPY]], 88, implicit-def $vl, implicit-def $vtype ; CHECK: [[PseudoVADD_VV_M1_:%[0-9]+]]:vr = PseudoVADD_VV_M1 [[COPY2]], [[COPY1]], $noreg, 6, implicit $vl, implicit $vtype ; CHECK: $v8 = COPY [[PseudoVADD_VV_M1_]] ; CHECK: PseudoRET implicit $v8 - %2:gpr = COPY $x10 + %2:gprnox0 = COPY $x10 %1:vr = COPY $v9 %0:vr = COPY $v8 %3:gpr = PseudoVSETVLI %2, 88, implicit-def dead $vl, implicit-def dead $vtype @@ -378,7 +378,7 @@ ; CHECK-LABEL: name: load_add_inlineasm ; CHECK: liveins: $x10, $v8, $x11 - ; CHECK: [[COPY:%[0-9]+]]:gpr = COPY $x11 + ; CHECK: [[COPY:%[0-9]+]]:gprnox0 = COPY $x11 ; CHECK: [[COPY1:%[0-9]+]]:vr = COPY $v8 ; CHECK: [[COPY2:%[0-9]+]]:gpr = COPY $x10 ; CHECK: dead $x0 = PseudoVSETVLI [[COPY]], 88, implicit-def $vl, implicit-def $vtype