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 @@ -75,6 +75,16 @@ return RVV->BaseInstr; } +static bool isFloatScalarMoveOrScalarSplatInstr(const MachineInstr &MI) { + switch (getRVVMCOpcode(MI.getOpcode())) { + default: + return false; + case RISCV::VFMV_S_F: + case RISCV::VFMV_V_F: + return true; + } +} + static bool isScalarMoveInstr(const MachineInstr &MI) { switch (getRVVMCOpcode(MI.getOpcode())) { default: @@ -192,10 +202,14 @@ bool VLZeroness = false; // What properties of SEW we need to preserve. enum : uint8_t { - SEWEqual = 2, // The exact value of SEW needs to be preserved. - SEWGreaterThanOrEqual = 1, // SEW can be changed as long as it's greater + SEWEqual = 3, // The exact value of SEW needs to be preserved. + SEWGreaterThanOrEqual = 2, // SEW can be changed as long as it's greater // than or equal to the original value. - SEWNone = 0 // We don't need to preserve SEW at all. + SEWGreaterThanOrEqualAndLessThan64 = + 1, // SEW can be changed as long as it's greater + // than or equal to the original value, but must + // less than 64 + SEWNone = 0 // We don't need to preserve SEW at all. } SEW = SEWNone; bool LMUL = false; bool SEWLMULRatio = false; @@ -244,6 +258,9 @@ case SEWEqual: OS << "SEWEqual"; break; + case SEWGreaterThanOrEqualAndLessThan64: + OS << "SEWGreaterThanOrEqualAndLessThan64"; + break; case SEWGreaterThanOrEqual: OS << "SEWGreaterThanOrEqual"; break; @@ -282,6 +299,11 @@ RISCVVType::getSEW(NewVType) < RISCVVType::getSEW(CurVType)) return false; + if (Used.SEW == DemandedFields::SEWGreaterThanOrEqualAndLessThan64 && + (RISCVVType::getSEW(NewVType) < RISCVVType::getSEW(CurVType) || + RISCVVType::getSEW(NewVType) >= 64)) + return false; + if (Used.LMUL && RISCVVType::getVLMUL(CurVType) != RISCVVType::getVLMUL(NewVType)) return false; @@ -306,7 +328,8 @@ /// Return the fields and properties demanded by the provided instruction. DemandedFields getDemanded(const MachineInstr &MI, - const MachineRegisterInfo *MRI) { + const MachineRegisterInfo *MRI, + bool hasVInstructionsF64) { // Warning: This function has to work on both the lowered (i.e. post // emitVSETVLIs) and pre-lowering forms. The main implication of this is // that it can't use the value of a SEW, VL, or Policy operand as they might @@ -369,7 +392,10 @@ // tail lanes to either be the original value or -1. We are writing // unknown bits to the lanes here. if (hasUndefinedMergeOp(MI, *MRI)) { - Res.SEW = DemandedFields::SEWGreaterThanOrEqual; + if (isFloatScalarMoveOrScalarSplatInstr(MI) && !hasVInstructionsF64) + Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64; + else + Res.SEW = DemandedFields::SEWGreaterThanOrEqual; Res.TailPolicy = false; } } @@ -690,6 +716,8 @@ std::vector BlockInfo; std::queue WorkList; + bool hasVInstructionsF64; + public: static char ID; @@ -920,7 +948,7 @@ if (!CurInfo.isValid() || CurInfo.isUnknown() || CurInfo.hasSEWLMULRatioOnly()) return true; - DemandedFields Used = getDemanded(MI, MRI); + DemandedFields Used = getDemanded(MI, MRI, hasVInstructionsF64); // A slidedown/slideup with an *undefined* merge op can freely clobber // elements not copied from the source vector (e.g. masked off, tail, or @@ -948,7 +976,10 @@ Used.LMUL = false; Used.SEWLMULRatio = false; Used.VLAny = false; - Used.SEW = DemandedFields::SEWGreaterThanOrEqual; + if (isFloatScalarMoveOrScalarSplatInstr(MI) && !hasVInstructionsF64) + Used.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64; + else + Used.SEW = DemandedFields::SEWGreaterThanOrEqual; Used.TailPolicy = false; } @@ -1437,7 +1468,7 @@ for (MachineInstr &MI : make_range(MBB.rbegin(), MBB.rend())) { if (!isVectorConfigInstr(MI)) { - doUnion(Used, getDemanded(MI, MRI)); + doUnion(Used, getDemanded(MI, MRI, hasVInstructionsF64)); continue; } @@ -1469,7 +1500,7 @@ } } NextMI = &MI; - Used = getDemanded(MI, MRI); + Used = getDemanded(MI, MRI, hasVInstructionsF64); } for (auto *MI : ToDelete) @@ -1500,6 +1531,7 @@ TII = ST.getInstrInfo(); MRI = &MF.getRegInfo(); + hasVInstructionsF64 = ST.hasVInstructionsF64(); assert(BlockInfo.empty() && "Expect empty block infos"); BlockInfo.resize(MF.getNumBlockIDs()); diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-valid-elen-fp.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-valid-elen-fp.ll --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-valid-elen-fp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-valid-elen-fp.ll @@ -9,6 +9,7 @@ ; CHECK-NO-FELEN64: # %bb.0: # %entry ; CHECK-NO-FELEN64-NEXT: vsetivli zero, 1, e64, m1, ta, ma ; CHECK-NO-FELEN64-NEXT: vle64.v v8, (a0) +; CHECK-NO-FELEN64-NEXT: vsetivli zero, 1, e16, m1, ta, ma ; CHECK-NO-FELEN64-NEXT: vfmv.s.f v9, fa0 ; CHECK-NO-FELEN64-NEXT: #APP ; CHECK-NO-FELEN64-NEXT: # use v8 v9