[llvm] [RISCV] Separate the analysis part of RISCVInsertVSETVLI. (PR #149574)
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 21 09:59:22 PDT 2025
================
@@ -0,0 +1,620 @@
+//===- RISCVVectorConfigAnalysis ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This is the RISCV analysis of vector unit config.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVVCONFIGANALYSIS_H
+#define LLVM_LIB_TARGET_RISCV_RISCVVCONFIGANALYSIS_H
+
+#include "RISCV.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LiveStacks.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include <queue>
+#include <vector>
+using namespace llvm;
+
+namespace llvm {
+/// Which subfields of VL or VTYPE have values we need to preserve?
+struct DemandedFields {
+ // Some unknown property of VL is used. If demanded, must preserve entire
+ // value.
+ bool VLAny = false;
+ // Only zero vs non-zero is used. If demanded, can change non-zero values.
+ bool VLZeroness = false;
+ // What properties of SEW we need to preserve.
+ enum : uint8_t {
+ SEWEqual = 3, // The exact value of SEW needs to be preserved.
+ SEWGreaterThanOrEqualAndLessThan64 =
+ 2, // SEW can be changed as long as it's greater
+ // than or equal to the original value, but must be less
+ // than 64.
+ SEWGreaterThanOrEqual = 1, // 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.
+ } SEW = SEWNone;
+ enum : uint8_t {
+ LMULEqual = 2, // The exact value of LMUL needs to be preserved.
+ LMULLessThanOrEqualToM1 = 1, // We can use any LMUL <= M1.
+ LMULNone = 0 // We don't need to preserve LMUL at all.
+ } LMUL = LMULNone;
+ bool SEWLMULRatio = false;
+ bool TailPolicy = false;
+ bool MaskPolicy = false;
+ // If this is true, we demand that VTYPE is set to some legal state, i.e. that
+ // vill is unset.
+ bool VILL = false;
+
+ // Return true if any part of VTYPE was used
+ bool usedVTYPE() const {
+ return SEW || LMUL || SEWLMULRatio || TailPolicy || MaskPolicy || VILL;
+ }
+
+ // Return true if any property of VL was used
+ bool usedVL() { return VLAny || VLZeroness; }
+
+ // Mark all VTYPE subfields and properties as demanded
+ void demandVTYPE() {
+ SEW = SEWEqual;
+ LMUL = LMULEqual;
+ SEWLMULRatio = true;
+ TailPolicy = true;
+ MaskPolicy = true;
+ VILL = true;
+ }
+
+ // Mark all VL properties as demanded
+ void demandVL() {
+ VLAny = true;
+ VLZeroness = true;
+ }
+
+ static DemandedFields all() {
+ DemandedFields DF;
+ DF.demandVTYPE();
+ DF.demandVL();
+ return DF;
+ }
+
+ // Make this the result of demanding both the fields in this and B.
+ void doUnion(const DemandedFields &B) {
+ VLAny |= B.VLAny;
+ VLZeroness |= B.VLZeroness;
+ SEW = std::max(SEW, B.SEW);
+ LMUL = std::max(LMUL, B.LMUL);
+ SEWLMULRatio |= B.SEWLMULRatio;
+ TailPolicy |= B.TailPolicy;
+ MaskPolicy |= B.MaskPolicy;
+ VILL |= B.VILL;
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Support for debugging, callable in GDB: V->dump()
+ LLVM_DUMP_METHOD void dump() const {
+ print(dbgs());
+ dbgs() << "\n";
+ }
+
+ /// Implement operator<<.
+ void print(raw_ostream &OS) const {
+ OS << "{";
+ OS << "VLAny=" << VLAny << ", ";
+ OS << "VLZeroness=" << VLZeroness << ", ";
+ OS << "SEW=";
+ switch (SEW) {
+ case SEWEqual:
+ OS << "SEWEqual";
+ break;
+ case SEWGreaterThanOrEqual:
+ OS << "SEWGreaterThanOrEqual";
+ break;
+ case SEWGreaterThanOrEqualAndLessThan64:
+ OS << "SEWGreaterThanOrEqualAndLessThan64";
+ break;
+ case SEWNone:
+ OS << "SEWNone";
+ break;
+ };
+ OS << ", ";
+ OS << "LMUL=";
+ switch (LMUL) {
+ case LMULEqual:
+ OS << "LMULEqual";
+ break;
+ case LMULLessThanOrEqualToM1:
+ OS << "LMULLessThanOrEqualToM1";
+ break;
+ case LMULNone:
+ OS << "LMULNone";
+ break;
+ };
+ OS << ", ";
+ OS << "SEWLMULRatio=" << SEWLMULRatio << ", ";
+ OS << "TailPolicy=" << TailPolicy << ", ";
+ OS << "MaskPolicy=" << MaskPolicy << ", ";
+ OS << "VILL=" << VILL;
+ OS << "}";
+ }
+#endif
+};
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_ATTRIBUTE_USED
+inline raw_ostream &operator<<(raw_ostream &OS, const DemandedFields &DF) {
+ DF.print(OS);
+ return OS;
+}
+#endif
+
+/// Defines the abstract state with which the forward dataflow models the
+/// values of the VL and VTYPE registers after insertion.
+class VSETVLIInfo {
+ struct AVLDef {
+ // Every AVLDef should have a VNInfo, unless we're running without
+ // LiveIntervals in which case this will be nullptr.
+ const VNInfo *ValNo;
+ Register DefReg;
+ };
+ union {
+ AVLDef AVLRegDef;
+ unsigned AVLImm;
+ };
+
+ enum : uint8_t {
+ Uninitialized,
+ AVLIsReg,
+ AVLIsImm,
+ AVLIsVLMAX,
+ Unknown, // AVL and VTYPE are fully unknown
+ } State = Uninitialized;
+
+ // Fields from VTYPE.
+ RISCVVType::VLMUL VLMul = RISCVVType::LMUL_1;
+ uint8_t SEW = 0;
+ uint8_t TailAgnostic : 1;
+ uint8_t MaskAgnostic : 1;
+ uint8_t SEWLMULRatioOnly : 1;
+
+public:
+ VSETVLIInfo()
+ : AVLImm(0), TailAgnostic(false), MaskAgnostic(false),
+ SEWLMULRatioOnly(false) {}
+
+ static VSETVLIInfo getUnknown() {
+ VSETVLIInfo Info;
+ Info.setUnknown();
+ return Info;
+ }
+
+ bool isValid() const { return State != Uninitialized; }
+ void setUnknown() { State = Unknown; }
+ bool isUnknown() const { return State == Unknown; }
+
+ void setAVLRegDef(const VNInfo *VNInfo, Register AVLReg) {
+ assert(AVLReg.isVirtual());
+ AVLRegDef.ValNo = VNInfo;
+ AVLRegDef.DefReg = AVLReg;
+ State = AVLIsReg;
+ }
+
+ void setAVLImm(unsigned Imm) {
+ AVLImm = Imm;
+ State = AVLIsImm;
+ }
+
+ void setAVLVLMAX() { State = AVLIsVLMAX; }
+
+ bool hasAVLImm() const { return State == AVLIsImm; }
+ bool hasAVLReg() const { return State == AVLIsReg; }
+ bool hasAVLVLMAX() const { return State == AVLIsVLMAX; }
+ Register getAVLReg() const {
+ assert(hasAVLReg() && AVLRegDef.DefReg.isVirtual());
+ return AVLRegDef.DefReg;
+ }
+ unsigned getAVLImm() const {
+ assert(hasAVLImm());
+ return AVLImm;
+ }
+ const VNInfo *getAVLVNInfo() const {
+ assert(hasAVLReg());
+ return AVLRegDef.ValNo;
+ }
+ // Most AVLIsReg infos will have a single defining MachineInstr, unless it was
+ // a PHI node. In that case getAVLVNInfo()->def will point to the block
+ // boundary slot and this will return nullptr. If LiveIntervals isn't
+ // available, nullptr is also returned.
+ const MachineInstr *getAVLDefMI(const LiveIntervals *LIS) const {
+ assert(hasAVLReg());
+ if (!LIS || getAVLVNInfo()->isPHIDef())
+ return nullptr;
+ auto *MI = LIS->getInstructionFromIndex(getAVLVNInfo()->def);
+ assert(MI);
+ return MI;
+ }
+
+ void setAVL(const VSETVLIInfo &Info) {
+ assert(Info.isValid());
+ if (Info.isUnknown())
+ setUnknown();
+ else if (Info.hasAVLReg())
+ setAVLRegDef(Info.getAVLVNInfo(), Info.getAVLReg());
+ else if (Info.hasAVLVLMAX())
+ setAVLVLMAX();
+ else {
+ assert(Info.hasAVLImm());
+ setAVLImm(Info.getAVLImm());
+ }
+ }
+
+ unsigned getSEW() const { return SEW; }
+ RISCVVType::VLMUL getVLMUL() const { return VLMul; }
+ bool getTailAgnostic() const { return TailAgnostic; }
+ bool getMaskAgnostic() const { return MaskAgnostic; }
+
+ bool hasNonZeroAVL(const LiveIntervals *LIS) const {
+ if (hasAVLImm())
+ return getAVLImm() > 0;
+ if (hasAVLReg()) {
+ if (auto *DefMI = getAVLDefMI(LIS))
+ return RISCVInstrInfo::isNonZeroLoadImmediate(*DefMI);
+ }
+ if (hasAVLVLMAX())
+ return true;
+ return false;
+ }
+
+ bool hasEquallyZeroAVL(const VSETVLIInfo &Other,
+ const LiveIntervals *LIS) const {
+ if (hasSameAVL(Other))
+ return true;
+ return (hasNonZeroAVL(LIS) && Other.hasNonZeroAVL(LIS));
+ }
+
+ bool hasSameAVLLatticeValue(const VSETVLIInfo &Other) const {
----------------
mshockwave wrote:
ditto move to .cpp file?
https://github.com/llvm/llvm-project/pull/149574
More information about the llvm-commits
mailing list