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 @@ -460,7 +460,7 @@ }; class RISCVInsertVSETVLI : public MachineFunctionPass { - const TargetInstrInfo *TII; + const RISCVInstrInfo *TII; MachineRegisterInfo *MRI; std::vector BlockInfo; @@ -925,6 +925,13 @@ if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVLMAX(CurInfo)) return false; } + + if (TII->isFaultFirstLoad(*DefMI)) { + uint64_t TSFlags = MI.getDesc().TSFlags; + VSETVLIInfo DefInfo = computeInfoForInstr(MI, TSFlags, MRI); + if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVLMAX(CurInfo)) + return false; + } } } @@ -965,11 +972,16 @@ } } - // If this is something that updates VL/VTYPE that we don't know about, set - // the state to unknown. - if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || - MI.modifiesRegister(RISCV::VTYPE)) + if (TII->isFaultFirstLoad(MI)) { + // Change AVL to the vl-output of VLEFF/VLSEGFF. + BBInfo.Change.setAVLReg(MI.getOperand(1).getReg()); + } else if ((MI.isCall() || MI.isInlineAsm() || + MI.modifiesRegister(RISCV::VL) || + MI.modifiesRegister(RISCV::VTYPE))) { + // If this is something that updates VL/VTYPE that we don't know about, + // set the state to unknown. BBInfo.Change = VSETVLIInfo::getUnknown(); + } } return HadVectorOp; @@ -1055,14 +1067,22 @@ if (PBBInfo.Exit.isUnknown() || !PBBInfo.Exit.hasSameVTYPE(Require)) return true; - // We need the PHI input to the be the output of a VSET(I)VLI. + // We need the PHI input to the be the output of a VSET(I)VLI/VLEFF/VLSEGFF. MachineInstr *DefMI = MRI->getVRegDef(InReg); - if (!DefMI || !isVectorConfigInstr(*DefMI)) + if (!DefMI || + (!isVectorConfigInstr(*DefMI) && !TII->isFaultFirstLoad(*DefMI))) return true; - // We found a VSET(I)VLI make sure it matches the output of the - // predecessor block. - VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); + // We found a VSET(I)VLI/VLEFF/VLSEGFF make sure it matches the output of + // the predecessor block. + VSETVLIInfo DefInfo; + if (TII->isFaultFirstLoad(*DefMI)) { + DefInfo = computeInfoForInstr(*DefMI, DefMI->getDesc().TSFlags, MRI); + DefInfo.setAVLReg(DefMI->getOperand(1).getReg()); + } else { + // DefMI is vector config instruction. + DefInfo = getInfoForVSETVLI(*DefMI); + } if (!DefInfo.hasSameAVL(PBBInfo.Exit) || !DefInfo.hasSameVTYPE(PBBInfo.Exit)) return true; @@ -1134,10 +1154,14 @@ } } - // If this is something that updates VL/VTYPE that we don't know about, set - // the state to unknown. - if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || - MI.modifiesRegister(RISCV::VTYPE)) { + if (TII->isFaultFirstLoad(MI)) { + // Change AVL to the vl-output of VLEFF/VLSEGFF. + CurInfo.setAVLReg(MI.getOperand(1).getReg()); + } else if ((MI.isCall() || MI.isInlineAsm() || + MI.modifiesRegister(RISCV::VL) || + MI.modifiesRegister(RISCV::VTYPE))) { + // If this is something that updates VL/VTYPE that we don't know about, + // set the state to unknown. CurInfo = VSETVLIInfo::getUnknown(); } } @@ -1412,9 +1436,6 @@ } void RISCVInsertVSETVLI::insertReadVL(MachineBasicBlock &MBB) { - const MachineFunction *MF = MBB.getParent(); - const RISCVInstrInfo *TII = MF->getSubtarget().getInstrInfo(); - for (auto I = MBB.begin(), E = MBB.end(); I != E;) { MachineInstr &MI = *I++; if (TII->isFaultFirstLoad(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 @@ -498,8 +498,7 @@ ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, mu ; CHECK-NEXT: vle64ff.v v8, (a0) -; CHECK-NEXT: csrr a0, vl -; CHECK-NEXT: vsetvli zero, a0, e64, m1, tu, mu +; CHECK-NEXT: vsetvli zero, zero, e64, m1, tu, mu ; CHECK-NEXT: vadd.vx v8, v8, a2 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-modify-vl.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-modify-vl.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-modify-vl.ll @@ -0,0 +1,83 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+v \ +; RUN: -target-abi=lp64d -verify-machineinstrs -< %s | FileCheck %s + +declare i64 @llvm.riscv.vsetvli.i64(i64, i64 immarg, i64 immarg) +declare { , i64 } @llvm.riscv.vleff.nxv32i8.i64(, * nocapture, i64) +declare @llvm.riscv.vmseq.nxv32i8.i8.i64(, i8, i64) +declare @llvm.riscv.vadd.nxv32i8.i8.i64(, , i8, i64) +declare @llvm.riscv.vadd.nxv16i16.i16.i64(, , i16, i64) + +define @seq1(i1 zeroext %cond, i8* %str, i64 %n, i8 %x) { +; CHECK-LABEL: seq1: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a2, e8, m4, ta, mu +; CHECK-NEXT: vle8ff.v v8, (a1) +; CHECK-NEXT: vadd.vx v8, v8, a3 +; CHECK-NEXT: vmseq.vi v0, v8, 0 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 0, i64 2) + %1 = bitcast i8* %str to * + %2 = tail call { , i64 } @llvm.riscv.vleff.nxv32i8.i64( undef, * %1, i64 %0) + %3 = extractvalue { , i64 } %2, 0 + %4 = extractvalue { , i64 } %2, 1 + %5 = tail call @llvm.riscv.vadd.nxv32i8.i8.i64( undef, %3, i8 %x, i64 %4) + %6 = tail call @llvm.riscv.vmseq.nxv32i8.i8.i64( %5, i8 0, i64 %4) + ret %6 +} + +define @cross_bb(i1 zeroext %cond, i8 zeroext %x, %vv, i8* %str, i64 %n) { +; CHECK-LABEL: cross_bb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a3, e8, m4, ta, mu +; CHECK-NEXT: beqz a0, .LBB1_2 +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: vle8ff.v v12, (a2) +; CHECK-NEXT: j .LBB1_3 +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: vsetvli a0, a3, e8, m4, ta, mu +; CHECK-NEXT: .LBB1_3: # %if.end +; CHECK-NEXT: vadd.vx v8, v8, a1 +; CHECK-NEXT: vadd.vx v8, v8, a1 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 0, i64 2) + br i1 %cond, label %if.then, label %if.else + +if.then: ; preds = %entry + %1 = bitcast i8* %str to * + %2 = tail call { , i64 } @llvm.riscv.vleff.nxv32i8.i64( undef, * %1, i64 %0) + %3 = extractvalue { , i64 } %2, 1 + br label %if.end + +if.else: ; preds = %entry + %4 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 0, i64 2) + br label %if.end + +if.end: ; preds = %if.else, %if.then + %new_vl.0 = phi i64 [ %3, %if.then ], [ %4, %if.else ] + %5 = tail call @llvm.riscv.vadd.nxv32i8.i8.i64( undef, %vv, i8 %x, i64 %new_vl.0) + %6 = tail call @llvm.riscv.vadd.nxv32i8.i8.i64( undef, %5, i8 %x, i64 %new_vl.0) + ret %6 +} + +; Test not eleminating useful vsetvli. +define @no_work(i1 zeroext %cond, i8* %str, i64 %n, %v, i16 %x) { +; CHECK-LABEL: no_work: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a2, e8, m4, ta, mu +; CHECK-NEXT: vle8ff.v v12, (a1) +; CHECK-NEXT: csrr a0, vl +; CHECK-NEXT: vsetvli zero, a0, e16, m4, ta, mu +; CHECK-NEXT: vadd.vx v8, v8, a3 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 0, i64 2) + %1 = bitcast i8* %str to * + %2 = tail call { , i64 } @llvm.riscv.vleff.nxv32i8.i64( undef, * %1, i64 %0) + %3 = extractvalue { , i64 } %2, 1 + %4 = tail call @llvm.riscv.vadd.nxv16i16.i16.i64( undef, %v, i16 %x, i64 %3) + ret %4 +} +