10b57cec5SDimitry Andric //===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the SetTheory class that computes ordered sets of 100b57cec5SDimitry Andric // Records from DAG expressions. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 141fd87a68SDimitry Andric #include "llvm/TableGen/SetTheory.h" 150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 180b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 190b57cec5SDimitry Andric #include "llvm/Support/Format.h" 200b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 220b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 230b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 240b57cec5SDimitry Andric #include <algorithm> 250b57cec5SDimitry Andric #include <cstdint> 260b57cec5SDimitry Andric #include <string> 270b57cec5SDimitry Andric #include <utility> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace llvm; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric // Define the standard operators. 320b57cec5SDimitry Andric namespace { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using RecSet = SetTheory::RecSet; 350b57cec5SDimitry Andric using RecVec = SetTheory::RecVec; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // (add a, b, ...) Evaluate and union all arguments. 380b57cec5SDimitry Andric struct AddOp : public SetTheory::Operator { 390b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 400b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 410b57cec5SDimitry Andric ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric }; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // (sub Add, Sub, ...) Set difference. 460b57cec5SDimitry Andric struct SubOp : public SetTheory::Operator { 470b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 480b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 490b57cec5SDimitry Andric if (Expr->arg_size() < 2) 500b57cec5SDimitry Andric PrintFatalError(Loc, "Set difference needs at least two arguments: " + 510b57cec5SDimitry Andric Expr->getAsString()); 520b57cec5SDimitry Andric RecSet Add, Sub; 530b57cec5SDimitry Andric ST.evaluate(*Expr->arg_begin(), Add, Loc); 540b57cec5SDimitry Andric ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc); 55fe6060f1SDimitry Andric for (const auto &I : Add) 56fe6060f1SDimitry Andric if (!Sub.count(I)) 57fe6060f1SDimitry Andric Elts.insert(I); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric }; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // (and S1, S2) Set intersection. 620b57cec5SDimitry Andric struct AndOp : public SetTheory::Operator { 630b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 640b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 650b57cec5SDimitry Andric if (Expr->arg_size() != 2) 660b57cec5SDimitry Andric PrintFatalError(Loc, "Set intersection requires two arguments: " + 670b57cec5SDimitry Andric Expr->getAsString()); 680b57cec5SDimitry Andric RecSet S1, S2; 690b57cec5SDimitry Andric ST.evaluate(Expr->arg_begin()[0], S1, Loc); 700b57cec5SDimitry Andric ST.evaluate(Expr->arg_begin()[1], S2, Loc); 71fe6060f1SDimitry Andric for (const auto &I : S1) 72fe6060f1SDimitry Andric if (S2.count(I)) 73fe6060f1SDimitry Andric Elts.insert(I); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric }; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // SetIntBinOp - Abstract base class for (Op S, N) operators. 780b57cec5SDimitry Andric struct SetIntBinOp : public SetTheory::Operator { 790b57cec5SDimitry Andric virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, 800b57cec5SDimitry Andric RecSet &Elts, ArrayRef<SMLoc> Loc) = 0; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 830b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 840b57cec5SDimitry Andric if (Expr->arg_size() != 2) 850b57cec5SDimitry Andric PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + 860b57cec5SDimitry Andric Expr->getAsString()); 870b57cec5SDimitry Andric RecSet Set; 880b57cec5SDimitry Andric ST.evaluate(Expr->arg_begin()[0], Set, Loc); 890b57cec5SDimitry Andric IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]); 900b57cec5SDimitry Andric if (!II) 910b57cec5SDimitry Andric PrintFatalError(Loc, "Second argument must be an integer: " + 920b57cec5SDimitry Andric Expr->getAsString()); 930b57cec5SDimitry Andric apply2(ST, Expr, Set, II->getValue(), Elts, Loc); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric }; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric // (shl S, N) Shift left, remove the first N elements. 980b57cec5SDimitry Andric struct ShlOp : public SetIntBinOp { 990b57cec5SDimitry Andric void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, 1000b57cec5SDimitry Andric RecSet &Elts, ArrayRef<SMLoc> Loc) override { 1010b57cec5SDimitry Andric if (N < 0) 1020b57cec5SDimitry Andric PrintFatalError(Loc, "Positive shift required: " + 1030b57cec5SDimitry Andric Expr->getAsString()); 1040b57cec5SDimitry Andric if (unsigned(N) < Set.size()) 1050b57cec5SDimitry Andric Elts.insert(Set.begin() + N, Set.end()); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric }; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // (trunc S, N) Truncate after the first N elements. 1100b57cec5SDimitry Andric struct TruncOp : public SetIntBinOp { 1110b57cec5SDimitry Andric void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, 1120b57cec5SDimitry Andric RecSet &Elts, ArrayRef<SMLoc> Loc) override { 1130b57cec5SDimitry Andric if (N < 0) 1140b57cec5SDimitry Andric PrintFatalError(Loc, "Positive length required: " + 1150b57cec5SDimitry Andric Expr->getAsString()); 1160b57cec5SDimitry Andric if (unsigned(N) > Set.size()) 1170b57cec5SDimitry Andric N = Set.size(); 1180b57cec5SDimitry Andric Elts.insert(Set.begin(), Set.begin() + N); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric }; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Left/right rotation. 1230b57cec5SDimitry Andric struct RotOp : public SetIntBinOp { 1240b57cec5SDimitry Andric const bool Reverse; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric RotOp(bool Rev) : Reverse(Rev) {} 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, 1290b57cec5SDimitry Andric RecSet &Elts, ArrayRef<SMLoc> Loc) override { 1300b57cec5SDimitry Andric if (Reverse) 1310b57cec5SDimitry Andric N = -N; 1320b57cec5SDimitry Andric // N > 0 -> rotate left, N < 0 -> rotate right. 1330b57cec5SDimitry Andric if (Set.empty()) 1340b57cec5SDimitry Andric return; 1350b57cec5SDimitry Andric if (N < 0) 1360b57cec5SDimitry Andric N = Set.size() - (-N % Set.size()); 1370b57cec5SDimitry Andric else 1380b57cec5SDimitry Andric N %= Set.size(); 1390b57cec5SDimitry Andric Elts.insert(Set.begin() + N, Set.end()); 1400b57cec5SDimitry Andric Elts.insert(Set.begin(), Set.begin() + N); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric }; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // (decimate S, N) Pick every N'th element of S. 1450b57cec5SDimitry Andric struct DecimateOp : public SetIntBinOp { 1460b57cec5SDimitry Andric void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, 1470b57cec5SDimitry Andric RecSet &Elts, ArrayRef<SMLoc> Loc) override { 1480b57cec5SDimitry Andric if (N <= 0) 1490b57cec5SDimitry Andric PrintFatalError(Loc, "Positive stride required: " + 1500b57cec5SDimitry Andric Expr->getAsString()); 1510b57cec5SDimitry Andric for (unsigned I = 0; I < Set.size(); I += N) 1520b57cec5SDimitry Andric Elts.insert(Set[I]); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric }; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // (interleave S1, S2, ...) Interleave elements of the arguments. 1570b57cec5SDimitry Andric struct InterleaveOp : public SetTheory::Operator { 1580b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 1590b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 1600b57cec5SDimitry Andric // Evaluate the arguments individually. 1610b57cec5SDimitry Andric SmallVector<RecSet, 4> Args(Expr->getNumArgs()); 1620b57cec5SDimitry Andric unsigned MaxSize = 0; 1630b57cec5SDimitry Andric for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { 1640b57cec5SDimitry Andric ST.evaluate(Expr->getArg(i), Args[i], Loc); 1650b57cec5SDimitry Andric MaxSize = std::max(MaxSize, unsigned(Args[i].size())); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric // Interleave arguments into Elts. 1680b57cec5SDimitry Andric for (unsigned n = 0; n != MaxSize; ++n) 1690b57cec5SDimitry Andric for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) 1700b57cec5SDimitry Andric if (n < Args[i].size()) 1710b57cec5SDimitry Andric Elts.insert(Args[i][n]); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric }; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // (sequence "Format", From, To) Generate a sequence of records by name. 1760b57cec5SDimitry Andric struct SequenceOp : public SetTheory::Operator { 1770b57cec5SDimitry Andric void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, 1780b57cec5SDimitry Andric ArrayRef<SMLoc> Loc) override { 1790b57cec5SDimitry Andric int Step = 1; 1800b57cec5SDimitry Andric if (Expr->arg_size() > 4) 1810b57cec5SDimitry Andric PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + 1820b57cec5SDimitry Andric Expr->getAsString()); 1830b57cec5SDimitry Andric else if (Expr->arg_size() == 4) { 1840b57cec5SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) { 1850b57cec5SDimitry Andric Step = II->getValue(); 1860b57cec5SDimitry Andric } else 1870b57cec5SDimitry Andric PrintFatalError(Loc, "Stride must be an integer: " + 1880b57cec5SDimitry Andric Expr->getAsString()); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric std::string Format; 1920b57cec5SDimitry Andric if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0])) 1935ffd83dbSDimitry Andric Format = std::string(SI->getValue()); 1940b57cec5SDimitry Andric else 1950b57cec5SDimitry Andric PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString()); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric int64_t From, To; 1980b57cec5SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1])) 1990b57cec5SDimitry Andric From = II->getValue(); 2000b57cec5SDimitry Andric else 2010b57cec5SDimitry Andric PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); 2020b57cec5SDimitry Andric if (From < 0 || From >= (1 << 30)) 2030b57cec5SDimitry Andric PrintFatalError(Loc, "From out of range"); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2])) 2060b57cec5SDimitry Andric To = II->getValue(); 2070b57cec5SDimitry Andric else 2080b57cec5SDimitry Andric PrintFatalError(Loc, "To must be an integer: " + Expr->getAsString()); 2090b57cec5SDimitry Andric if (To < 0 || To >= (1 << 30)) 2100b57cec5SDimitry Andric PrintFatalError(Loc, "To out of range"); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric RecordKeeper &Records = 2130b57cec5SDimitry Andric cast<DefInit>(Expr->getOperator())->getDef()->getRecords(); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric Step *= From <= To ? 1 : -1; 2160b57cec5SDimitry Andric while (true) { 2170b57cec5SDimitry Andric if (Step > 0 && From > To) 2180b57cec5SDimitry Andric break; 2190b57cec5SDimitry Andric else if (Step < 0 && From < To) 2200b57cec5SDimitry Andric break; 2210b57cec5SDimitry Andric std::string Name; 2220b57cec5SDimitry Andric raw_string_ostream OS(Name); 2230b57cec5SDimitry Andric OS << format(Format.c_str(), unsigned(From)); 224*0fca6ea1SDimitry Andric Record *Rec = Records.getDef(Name); 2250b57cec5SDimitry Andric if (!Rec) 2260b57cec5SDimitry Andric PrintFatalError(Loc, "No def named '" + Name + "': " + 2270b57cec5SDimitry Andric Expr->getAsString()); 2280b57cec5SDimitry Andric // Try to reevaluate Rec in case it is a set. 2290b57cec5SDimitry Andric if (const RecVec *Result = ST.expand(Rec)) 2300b57cec5SDimitry Andric Elts.insert(Result->begin(), Result->end()); 2310b57cec5SDimitry Andric else 2320b57cec5SDimitry Andric Elts.insert(Rec); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric From += Step; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric }; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric // Expand a Def into a set by evaluating one of its fields. 2400b57cec5SDimitry Andric struct FieldExpander : public SetTheory::Expander { 2410b57cec5SDimitry Andric StringRef FieldName; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric FieldExpander(StringRef fn) : FieldName(fn) {} 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric void expand(SetTheory &ST, Record *Def, RecSet &Elts) override { 2460b57cec5SDimitry Andric ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric }; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric } // end anonymous namespace 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // Pin the vtables to this file. 2530b57cec5SDimitry Andric void SetTheory::Operator::anchor() {} 2540b57cec5SDimitry Andric void SetTheory::Expander::anchor() {} 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric SetTheory::SetTheory() { 2578bcb0991SDimitry Andric addOperator("add", std::make_unique<AddOp>()); 2588bcb0991SDimitry Andric addOperator("sub", std::make_unique<SubOp>()); 2598bcb0991SDimitry Andric addOperator("and", std::make_unique<AndOp>()); 2608bcb0991SDimitry Andric addOperator("shl", std::make_unique<ShlOp>()); 2618bcb0991SDimitry Andric addOperator("trunc", std::make_unique<TruncOp>()); 2628bcb0991SDimitry Andric addOperator("rotl", std::make_unique<RotOp>(false)); 2638bcb0991SDimitry Andric addOperator("rotr", std::make_unique<RotOp>(true)); 2648bcb0991SDimitry Andric addOperator("decimate", std::make_unique<DecimateOp>()); 2658bcb0991SDimitry Andric addOperator("interleave", std::make_unique<InterleaveOp>()); 2668bcb0991SDimitry Andric addOperator("sequence", std::make_unique<SequenceOp>()); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric void SetTheory::addOperator(StringRef Name, std::unique_ptr<Operator> Op) { 2700b57cec5SDimitry Andric Operators[Name] = std::move(Op); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric void SetTheory::addExpander(StringRef ClassName, std::unique_ptr<Expander> E) { 2740b57cec5SDimitry Andric Expanders[ClassName] = std::move(E); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { 2788bcb0991SDimitry Andric addExpander(ClassName, std::make_unique<FieldExpander>(FieldName)); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { 2820b57cec5SDimitry Andric // A def in a list can be a just an element, or it may expand. 2830b57cec5SDimitry Andric if (DefInit *Def = dyn_cast<DefInit>(Expr)) { 2840b57cec5SDimitry Andric if (const RecVec *Result = expand(Def->getDef())) 2850b57cec5SDimitry Andric return Elts.insert(Result->begin(), Result->end()); 2860b57cec5SDimitry Andric Elts.insert(Def->getDef()); 2870b57cec5SDimitry Andric return; 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Lists simply expand. 2910b57cec5SDimitry Andric if (ListInit *LI = dyn_cast<ListInit>(Expr)) 2920b57cec5SDimitry Andric return evaluate(LI->begin(), LI->end(), Elts, Loc); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // Anything else must be a DAG. 2950b57cec5SDimitry Andric DagInit *DagExpr = dyn_cast<DagInit>(Expr); 2960b57cec5SDimitry Andric if (!DagExpr) 2970b57cec5SDimitry Andric PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString()); 2980b57cec5SDimitry Andric DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator()); 2990b57cec5SDimitry Andric if (!OpInit) 3000b57cec5SDimitry Andric PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString()); 3010b57cec5SDimitry Andric auto I = Operators.find(OpInit->getDef()->getName()); 3020b57cec5SDimitry Andric if (I == Operators.end()) 3030b57cec5SDimitry Andric PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString()); 3040b57cec5SDimitry Andric I->second->apply(*this, DagExpr, Elts, Loc); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric const RecVec *SetTheory::expand(Record *Set) { 3080b57cec5SDimitry Andric // Check existing entries for Set and return early. 3090b57cec5SDimitry Andric ExpandMap::iterator I = Expansions.find(Set); 3100b57cec5SDimitry Andric if (I != Expansions.end()) 3110b57cec5SDimitry Andric return &I->second; 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // This is the first time we see Set. Find a suitable expander. 3140b57cec5SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SC = Set->getSuperClasses(); 3150b57cec5SDimitry Andric for (const auto &SCPair : SC) { 3160b57cec5SDimitry Andric // Skip unnamed superclasses. 3170b57cec5SDimitry Andric if (!isa<StringInit>(SCPair.first->getNameInit())) 3180b57cec5SDimitry Andric continue; 3190b57cec5SDimitry Andric auto I = Expanders.find(SCPair.first->getName()); 3200b57cec5SDimitry Andric if (I != Expanders.end()) { 3210b57cec5SDimitry Andric // This breaks recursive definitions. 3220b57cec5SDimitry Andric RecVec &EltVec = Expansions[Set]; 3230b57cec5SDimitry Andric RecSet Elts; 3240b57cec5SDimitry Andric I->second->expand(*this, Set, Elts); 3250b57cec5SDimitry Andric EltVec.assign(Elts.begin(), Elts.end()); 3260b57cec5SDimitry Andric return &EltVec; 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Set is not expandable. 3310b57cec5SDimitry Andric return nullptr; 3320b57cec5SDimitry Andric } 333