diff options
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
| -rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 160 | 
1 files changed, 60 insertions, 100 deletions
| diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 5cce1f5218c..d1821b64dd8 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -110,28 +110,30 @@ public:    const LLT &get() const { return Ty; }    /// This ordering is used for std::unique() and std::sort(). There's no -  /// particular logic behind the order but either A < B or B < A must be -  /// true if A != B. +  /// particular logic behind the order.    bool operator<(const LLTCodeGen &Other) const { -    if (Ty.isValid() != Other.Ty.isValid()) -      return Ty.isValid() < Other.Ty.isValid();      if (!Ty.isValid()) +      return Other.Ty.isValid(); +    if (Ty.isScalar()) { +      if (!Other.Ty.isValid()) +        return false; +      if (Other.Ty.isScalar()) +        return Ty.getSizeInBits() < Other.Ty.getSizeInBits();        return false; - -    if (Ty.isVector() != Other.Ty.isVector()) -      return Ty.isVector() < Other.Ty.isVector(); -    if (Ty.isScalar() != Other.Ty.isScalar()) -      return Ty.isScalar() < Other.Ty.isScalar(); -    if (Ty.isPointer() != Other.Ty.isPointer()) -      return Ty.isPointer() < Other.Ty.isPointer(); - -    if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace()) -      return Ty.getAddressSpace() < Other.Ty.getAddressSpace(); - -    if (Ty.isVector() && Ty.getNumElements() != Other.Ty.getNumElements()) -      return Ty.getNumElements() < Other.Ty.getNumElements(); - -    return Ty.getSizeInBits() < Other.Ty.getSizeInBits(); +    } +    if (Ty.isVector()) { +      if (!Other.Ty.isValid() || Other.Ty.isScalar()) +        return false; +      if (Other.Ty.isVector()) { +        if (Ty.getNumElements() < Other.Ty.getNumElements()) +          return true; +        if (Ty.getNumElements() > Other.Ty.getNumElements()) +          return false; +        return Ty.getSizeInBits() < Other.Ty.getSizeInBits(); +      } +      return false; +    } +    llvm_unreachable("Unhandled LLT");    }  }; @@ -180,6 +182,14 @@ static Error failedImport(const Twine &Reason) {  static Error isTrivialOperatorNode(const TreePatternNode *N) {    std::string Explanation = "";    std::string Separator = ""; +  if (N->isLeaf()) { +    if (isa<IntInit>(N->getLeafValue())) +      return Error::success(); + +    Explanation = "Is a leaf"; +    Separator = ", "; +  } +    if (N->hasAnyPredicate()) {      Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";      Separator = ", "; @@ -190,7 +200,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {      Separator = ", ";    } -  if (!N->hasAnyPredicate() && !N->getTransformFn()) +  if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())      return Error::success();    return failedImport(Explanation); @@ -448,9 +458,7 @@ class RuleMatcher {    /// A list of actions that need to be taken when all predicates in this rule    /// have succeeded. -public:    std::vector<std::unique_ptr<MatchAction>> Actions; -protected:    typedef std::map<const InstructionMatcher *, unsigned>        DefinedInsnVariablesMap; @@ -626,12 +634,8 @@ protected:    LLTCodeGen Ty;  public: -  static std::set<LLTCodeGen> KnownTypes; -    LLTOperandMatcher(const LLTCodeGen &Ty) -      : OperandPredicateMatcher(OPM_LLT), Ty(Ty) { -    KnownTypes.insert(Ty); -  } +      : OperandPredicateMatcher(OPM_LLT), Ty(Ty) {}    static bool classof(const OperandPredicateMatcher *P) {      return P->getKind() == OPM_LLT; @@ -647,8 +651,6 @@ public:    }  }; -std::set<LLTCodeGen> LLTOperandMatcher::KnownTypes; -  /// Generates code to check that an operand is a particular target constant.  class ComplexPatternOperandMatcher : public OperandPredicateMatcher {  protected: @@ -1434,9 +1436,7 @@ public:  class BuildMIAction : public MatchAction {  private:    unsigned InsnID; -public:    const CodeGenInstruction *I; -private:    const InstructionMatcher &Matched;    std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers; @@ -2287,42 +2287,8 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {      return failedImport("Src pattern root isn't a trivial operator (" +                          toString(std::move(Err)) + ")"); -  InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName()); -  unsigned TempOpIdx = 0; -  auto InsnMatcherOrError = -      createAndImportSelDAGMatcher(InsnMatcherTemp, Src, TempOpIdx); -  if (auto Error = InsnMatcherOrError.takeError()) -    return std::move(Error); -  InstructionMatcher &InsnMatcher = InsnMatcherOrError.get(); - -  if (Dst->isLeaf()) { -    Record *RCDef = getInitValueAsRegClass(Dst->getLeafValue()); - -    const CodeGenRegisterClass &RC = Target.getRegisterClass(RCDef); -    if (RCDef) { -      // We need to replace the def and all its uses with the specified -      // operand. However, we must also insert COPY's wherever needed. -      // For now, emit a copy and let the register allocator clean up. -      auto &DstI = Target.getInstruction(RK.getDef("COPY")); -      const auto &DstIOperand = DstI.Operands[0]; - -      OperandMatcher &OM0 = InsnMatcher.getOperand(0); -      OM0.setSymbolicName(DstIOperand.Name); -      OM0.addPredicate<RegisterBankOperandMatcher>(RC); - -      auto &DstMIBuilder = M.addAction<BuildMIAction>(0, &DstI, InsnMatcher); -      DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, DstIOperand.Name); -      DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, Dst->getName()); -      M.addAction<ConstrainOperandToRegClassAction>(0, 0, RC); - -      // We're done with this pattern!  It's eligible for GISel emission; return -      // it. -      ++NumPatternImported; -      return std::move(M); -    } - +  if (Dst->isLeaf())      return failedImport("Dst pattern root isn't a known leaf"); -  }    // Start with the defined operands (i.e., the results of the root operator).    Record *DstOp = Dst->getOperator(); @@ -2335,6 +2301,14 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {                          to_string(Src->getExtTypes().size()) + " def(s) vs " +                          to_string(DstI.Operands.NumDefs) + " def(s))"); +  InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName()); +  unsigned TempOpIdx = 0; +  auto InsnMatcherOrError = +      createAndImportSelDAGMatcher(InsnMatcherTemp, Src, TempOpIdx); +  if (auto Error = InsnMatcherOrError.takeError()) +    return std::move(Error); +  InstructionMatcher &InsnMatcher = InsnMatcherOrError.get(); +    // The root of the match also has constraints on the register bank so that it    // matches the result instruction.    unsigned OpIdx = 0; @@ -2482,37 +2456,16 @@ void GlobalISelEmitter::run(raw_ostream &OS) {      Rules.push_back(std::move(MatcherOrErr.get()));    } -  const auto &IsRuleEmittingOpcode = [](const RuleMatcher &A, StringRef I) -> bool { -    const BuildMIAction &BMI = (const BuildMIAction &)*A.Actions[1]; -    if (BMI.I->TheDef->getName() == I) -      return true; -    return false; -  }; - -  std::stable_sort(Rules.begin(), Rules.end(), [&](const RuleMatcher &A, -                                                   const RuleMatcher &B) { -    bool EmitResult = false; -    bool AIsADD8ri = false; -    if (IsRuleEmittingOpcode(A, "ADD8ri") && IsRuleEmittingOpcode(B, "INC8r")) { -      EmitResult = true; -      AIsADD8ri = true; -    } -    if (IsRuleEmittingOpcode(B, "ADD8ri") && IsRuleEmittingOpcode(A, "INC8r")) -      EmitResult = true; - -    if (EmitResult) -      errs() << "A=" << (AIsADD8ri ? "ADD8ri" : "INC8r") << ", B=" << (!AIsADD8ri ? "ADD8ri" : "INC8r") << "\n"; -    if (A.isHigherPriorityThan(B)) { -      if (EmitResult) -        errs() << "A higher priority than B\n"; -      assert(!B.isHigherPriorityThan(A) && "Cannot be more important " -                                           "and less important at " -                                           "the same time"); -      return true; -    } else if (EmitResult) -      errs() << "A lower priority than B\n"; -    return false; -  }); +  std::stable_sort(Rules.begin(), Rules.end(), +            [&](const RuleMatcher &A, const RuleMatcher &B) { +              if (A.isHigherPriorityThan(B)) { +                assert(!B.isHigherPriorityThan(A) && "Cannot be more important " +                                                     "and less important at " +                                                     "the same time"); +                return true; +              } +              return false; +            });    std::vector<Record *> ComplexPredicates =        RK.getAllDerivedDefinitions("GIComplexOperandMatcher"); @@ -2582,9 +2535,16 @@ void GlobalISelEmitter::run(raw_ostream &OS) {    // Emit a table containing the LLT objects needed by the matcher and an enum    // for the matcher to reference them with. -  std::vector<LLTCodeGen> TypeObjects; -  for (const auto &Ty : LLTOperandMatcher::KnownTypes) -    TypeObjects.push_back(Ty); +  std::vector<LLTCodeGen> TypeObjects = { +      LLT::scalar(8),      LLT::scalar(16),     LLT::scalar(32), +      LLT::scalar(64),     LLT::scalar(80),     LLT::vector(8, 1), +      LLT::vector(16, 1),  LLT::vector(32, 1),  LLT::vector(64, 1), +      LLT::vector(8, 8),   LLT::vector(16, 8),  LLT::vector(32, 8), +      LLT::vector(64, 8),  LLT::vector(4, 16),  LLT::vector(8, 16), +      LLT::vector(16, 16), LLT::vector(32, 16), LLT::vector(2, 32), +      LLT::vector(4, 32),  LLT::vector(8, 32),  LLT::vector(16, 32), +      LLT::vector(2, 64),  LLT::vector(4, 64),  LLT::vector(8, 64), +  };    std::sort(TypeObjects.begin(), TypeObjects.end());    OS << "enum {\n";    for (const auto &TypeObject : TypeObjects) { | 

