diff --git a/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp b/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp index f519e3b2fd3b1..ff7718c9ef6d9 100644 --- a/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp +++ b/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp @@ -80,13 +80,13 @@ class RISCVInitUndef : public MachineFunctionPass { private: bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, const DeadLaneDetector &DLD); - bool handleImplicitDef(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &Inst); bool isVectorRegClass(const Register R); const TargetRegisterClass * getVRLargestSuperClass(const TargetRegisterClass *RC) const; bool handleSubReg(MachineFunction &MF, MachineInstr &MI, const DeadLaneDetector &DLD); + bool fixupIllOperand(MachineInstr *MI, MachineOperand &MO); + bool handleReg(MachineInstr *MI); }; } // end anonymous namespace @@ -137,53 +137,30 @@ static bool isEarlyClobberMI(MachineInstr &MI) { }); } -bool RISCVInitUndef::handleImplicitDef(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &Inst) { - assert(Inst->getOpcode() == TargetOpcode::IMPLICIT_DEF); - - Register Reg = Inst->getOperand(0).getReg(); - if (!Reg.isVirtual()) - return false; - - bool HasOtherUse = false; - SmallVector UseMOs; - for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) { - if (isEarlyClobberMI(*MO.getParent())) { - if (MO.isUse() && !MO.isTied()) - UseMOs.push_back(&MO); - else - HasOtherUse = true; - } +static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) { + for (auto &DefMI : MRI->def_instructions(Reg)) { + if (DefMI.getOpcode() == TargetOpcode::IMPLICIT_DEF) + return true; } + return false; +} - if (UseMOs.empty()) - return false; - - LLVM_DEBUG( - dbgs() << "Emitting PseudoRVVInitUndef for implicit vector register " - << Reg << '\n'); - - const TargetRegisterClass *TargetRegClass = - getVRLargestSuperClass(MRI->getRegClass(Reg)); - unsigned Opcode = getUndefInitOpcode(TargetRegClass->getID()); - - Register NewDest = Reg; - if (HasOtherUse) { - NewDest = MRI->createVirtualRegister(TargetRegClass); - // We don't have a way to update dead lanes, so keep track of the - // new register so that we avoid querying it later. - NewRegs.insert(NewDest); - } - BuildMI(MBB, Inst, Inst->getDebugLoc(), TII->get(Opcode), NewDest); - - if (!HasOtherUse) - DeadInsts.push_back(&(*Inst)); +bool RISCVInitUndef::handleReg(MachineInstr *MI) { + bool Changed = false; + for (auto &UseMO : MI->uses()) { + if (!UseMO.isReg()) + continue; + if (UseMO.isTied()) + continue; + if (!UseMO.getReg().isVirtual()) + continue; + if (!isVectorRegClass(UseMO.getReg())) + continue; - for (auto MO : UseMOs) { - MO->setReg(NewDest); - MO->setIsUndef(false); + if (UseMO.isUndef() || findImplictDefMIFromReg(UseMO.getReg(), MRI)) + Changed |= fixupIllOperand(MI, UseMO); } - return true; + return Changed; } bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI, @@ -248,6 +225,23 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI, return Changed; } +bool RISCVInitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) { + + LLVM_DEBUG( + dbgs() << "Emitting PseudoRVVInitUndef for implicit vector register " + << MO.getReg() << '\n'); + + const TargetRegisterClass *TargetRegClass = + getVRLargestSuperClass(MRI->getRegClass(MO.getReg())); + unsigned Opcode = getUndefInitOpcode(TargetRegClass->getID()); + Register NewReg = MRI->createVirtualRegister(TargetRegClass); + BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(Opcode), NewReg); + MO.setReg(NewReg); + if (MO.isUndef()) + MO.setIsUndef(false); + return true; +} + bool RISCVInitUndef::processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, const DeadLaneDetector &DLD) { @@ -274,12 +268,10 @@ bool RISCVInitUndef::processBasicBlock(MachineFunction &MF, } } - if (ST->enableSubRegLiveness() && isEarlyClobberMI(MI)) - Changed |= handleSubReg(MF, MI, DLD); - if (MI.isImplicitDef()) { - auto DstReg = MI.getOperand(0).getReg(); - if (DstReg.isVirtual() && isVectorRegClass(DstReg)) - Changed |= handleImplicitDef(MBB, I); + if (isEarlyClobberMI(MI)) { + if (ST->enableSubRegLiveness()) + Changed |= handleSubReg(MF, MI, DLD); + Changed |= handleReg(&MI); } } return Changed; diff --git a/llvm/test/CodeGen/RISCV/65704-illegal-instruction.ll b/llvm/test/CodeGen/RISCV/65704-illegal-instruction.ll new file mode 100644 index 0000000000000..3181fa60cfa23 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/65704-illegal-instruction.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -mtriple=riscv64 -mattr=+v,+f,+m,+zfh,+zvfh \ +; RUN: < %s | FileCheck %s + +declare <16 x i8> @llvm.vector.extract.v16i8.nxv8i8(, i64 immarg) +declare @llvm.vector.insert.nxv8i8.v16i8(, <16 x i8>, i64 immarg) +declare @llvm.riscv.vslideup.nxv8i8.i64(, , i64, i64, i64 immarg) +declare @llvm.vector.insert.nxv2i32.v4i32(, <4 x i32>, i64 immarg) + +define void @foo( %0) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: .cfi_offset ra, -8 +; CHECK-NEXT: .cfi_offset s0, -16 +; CHECK-NEXT: .cfi_offset s1, -24 +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vmv.v.i v9, 0 +; CHECK-NEXT: vsetivli zero, 0, e8, m1, tu, ma +; CHECK-NEXT: vslideup.vi v9, v10, 0 +; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; CHECK-NEXT: vmv.x.s s0, v9 +; CHECK-NEXT: vsetivli zero, 0, e8, m1, tu, ma +; CHECK-NEXT: vslideup.vi v8, v9, 0 +; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; CHECK-NEXT: vmv.x.s s1, v8 +; CHECK-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: mv a0, s0 +; CHECK-NEXT: mv a2, s1 +; CHECK-NEXT: li a3, 0 +; CHECK-NEXT: li a4, 0 +; CHECK-NEXT: li a5, 0 +; CHECK-NEXT: jalr a1 +; CHECK-NEXT: j .LBB0_1 + %2 = tail call @llvm.vector.insert.nxv8i8.v16i8( undef, <16 x i8> undef, i64 0) + %3 = tail call @llvm.vector.insert.nxv8i8.v16i8( undef, <16 x i8> poison, i64 0) + br label %4 + +4: ; preds = %4, %1 + %5 = tail call @llvm.riscv.vslideup.nxv8i8.i64( zeroinitializer, %2, i64 0, i64 0, i64 0) + %6 = tail call <16 x i8> @llvm.vector.extract.v16i8.nxv8i8( %5, i64 0) + %7 = bitcast <16 x i8> %6 to <2 x i64> + %8 = extractelement <2 x i64> %7, i64 0 + %9 = insertvalue [2 x i64] zeroinitializer, i64 %8, 0 + %10 = tail call @llvm.riscv.vslideup.nxv8i8.i64( %0, %3, i64 0, i64 0, i64 0) + %11 = tail call <16 x i8> @llvm.vector.extract.v16i8.nxv8i8( %10, i64 0) + %12 = bitcast <16 x i8> %11 to <2 x i64> + %13 = extractelement <2 x i64> %12, i64 0 + %14 = insertvalue [2 x i64] zeroinitializer, i64 %13, 0 + %15 = tail call fastcc [2 x i64] null([2 x i64] %9, [2 x i64] %14, [2 x i64] zeroinitializer) + br label %4 +} diff --git a/llvm/test/CodeGen/RISCV/rvv/handle-noreg-with-implicit-def.mir b/llvm/test/CodeGen/RISCV/rvv/handle-noreg-with-implicit-def.mir index 9ed3de951d03a..4102aa8aa4d72 100644 --- a/llvm/test/CodeGen/RISCV/rvv/handle-noreg-with-implicit-def.mir +++ b/llvm/test/CodeGen/RISCV/rvv/handle-noreg-with-implicit-def.mir @@ -7,9 +7,10 @@ tracksRegLiveness: true body: | bb.0.entry: ; MIR-LABEL: name: vrgather_all_undef - ; MIR: [[PseudoRVVInitUndefM1_:%[0-9]+]]:vr = PseudoRVVInitUndefM1 - ; MIR-NEXT: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF - ; MIR-NEXT: early-clobber %1:vr = PseudoVRGATHER_VI_M1 [[DEF]], killed [[PseudoRVVInitUndefM1_]], 0, 0, 5 /* e32 */, 0 /* tu, mu */ + ; MIR: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; MIR-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; MIR-NEXT: [[PseudoRVVInitUndefM1_:%[0-9]+]]:vr = PseudoRVVInitUndefM1 + ; MIR-NEXT: early-clobber %1:vr = PseudoVRGATHER_VI_M1 [[DEF1]], killed [[PseudoRVVInitUndefM1_]], 0, 0, 5 /* e32 */, 0 /* tu, mu */ ; MIR-NEXT: $v8 = COPY %1 ; MIR-NEXT: PseudoRET implicit $v8 %2:vr = IMPLICIT_DEF diff --git a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.mir b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.mir index 08ea967179ebf..58b2687824aa1 100644 --- a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.mir +++ b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.mir @@ -76,9 +76,9 @@ machineFunctionInfo: body: | bb.0.entry: ; CHECK-LABEL: name: undef_early_clobber_chain - ; CHECK: [[PseudoRVVInitUndefM1_:%[0-9]+]]:vr = PseudoRVVInitUndefM1 - ; CHECK-NEXT: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; CHECK: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 0, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + ; CHECK-NEXT: [[PseudoRVVInitUndefM1_:%[0-9]+]]:vr = PseudoRVVInitUndefM1 ; CHECK-NEXT: early-clobber %1:vr = PseudoVRGATHER_VI_M1 undef [[DEF]], [[PseudoRVVInitUndefM1_]], 0, 0, 5 /* e32 */, 0 /* tu, mu */, implicit $vl, implicit $vtype ; CHECK-NEXT: $v8 = COPY %1 ; CHECK-NEXT: PseudoRET implicit $v8