SetTheory.cpp revision f37dd02f7743ebd2424480361f5a7db510495c4f
1//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the SetTheory class that computes ordered sets of 11// Records from DAG expressions. 12// 13//===----------------------------------------------------------------------===// 14 15#include "SetTheory.h" 16#include "Error.h" 17#include "Record.h" 18#include "llvm/Support/Format.h" 19 20using namespace llvm; 21 22// Define the standard operators. 23namespace { 24 25typedef SetTheory::RecSet RecSet; 26typedef SetTheory::RecVec RecVec; 27 28// (add a, b, ...) Evaluate and union all arguments. 29struct AddOp : public SetTheory::Operator { 30 void apply(SetTheory &ST, const DagInit *Expr, RecSet &Elts) { 31 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts); 32 } 33}; 34 35// (sub Add, Sub, ...) Set difference. 36struct SubOp : public SetTheory::Operator { 37 void apply(SetTheory &ST, const DagInit *Expr, RecSet &Elts) { 38 if (Expr->arg_size() < 2) 39 throw "Set difference needs at least two arguments: " + 40 Expr->getAsString(); 41 RecSet Add, Sub; 42 ST.evaluate(*Expr->arg_begin(), Add); 43 ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub); 44 for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) 45 if (!Sub.count(*I)) 46 Elts.insert(*I); 47 } 48}; 49 50// (and S1, S2) Set intersection. 51struct AndOp : public SetTheory::Operator { 52 void apply(SetTheory &ST, const DagInit *Expr, RecSet &Elts) { 53 if (Expr->arg_size() != 2) 54 throw "Set intersection requires two arguments: " + Expr->getAsString(); 55 RecSet S1, S2; 56 ST.evaluate(Expr->arg_begin()[0], S1); 57 ST.evaluate(Expr->arg_begin()[1], S2); 58 for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) 59 if (S2.count(*I)) 60 Elts.insert(*I); 61 } 62}; 63 64// SetIntBinOp - Abstract base class for (Op S, N) operators. 65struct SetIntBinOp : public SetTheory::Operator { 66 virtual void apply2(SetTheory &ST, const DagInit *Expr, 67 RecSet &Set, int64_t N, 68 RecSet &Elts) =0; 69 70 void apply(SetTheory &ST, const DagInit *Expr, RecSet &Elts) { 71 if (Expr->arg_size() != 2) 72 throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString(); 73 RecSet Set; 74 ST.evaluate(Expr->arg_begin()[0], Set); 75 const IntInit *II = dynamic_cast<const IntInit*>(Expr->arg_begin()[1]); 76 if (!II) 77 throw "Second argument must be an integer: " + Expr->getAsString(); 78 apply2(ST, Expr, Set, II->getValue(), Elts); 79 } 80}; 81 82// (shl S, N) Shift left, remove the first N elements. 83struct ShlOp : public SetIntBinOp { 84 void apply2(SetTheory &ST, const DagInit *Expr, 85 RecSet &Set, int64_t N, 86 RecSet &Elts) { 87 if (N < 0) 88 throw "Positive shift required: " + Expr->getAsString(); 89 if (unsigned(N) < Set.size()) 90 Elts.insert(Set.begin() + N, Set.end()); 91 } 92}; 93 94// (trunc S, N) Truncate after the first N elements. 95struct TruncOp : public SetIntBinOp { 96 void apply2(SetTheory &ST, const DagInit *Expr, 97 RecSet &Set, int64_t N, 98 RecSet &Elts) { 99 if (N < 0) 100 throw "Positive length required: " + Expr->getAsString(); 101 if (unsigned(N) > Set.size()) 102 N = Set.size(); 103 Elts.insert(Set.begin(), Set.begin() + N); 104 } 105}; 106 107// Left/right rotation. 108struct RotOp : public SetIntBinOp { 109 const bool Reverse; 110 111 RotOp(bool Rev) : Reverse(Rev) {} 112 113 void apply2(SetTheory &ST, const DagInit *Expr, 114 RecSet &Set, int64_t N, 115 RecSet &Elts) { 116 if (Reverse) 117 N = -N; 118 // N > 0 -> rotate left, N < 0 -> rotate right. 119 if (Set.empty()) 120 return; 121 if (N < 0) 122 N = Set.size() - (-N % Set.size()); 123 else 124 N %= Set.size(); 125 Elts.insert(Set.begin() + N, Set.end()); 126 Elts.insert(Set.begin(), Set.begin() + N); 127 } 128}; 129 130// (decimate S, N) Pick every N'th element of S. 131struct DecimateOp : public SetIntBinOp { 132 void apply2(SetTheory &ST, const DagInit *Expr, 133 RecSet &Set, int64_t N, 134 RecSet &Elts) { 135 if (N <= 0) 136 throw "Positive stride required: " + Expr->getAsString(); 137 for (unsigned I = 0; I < Set.size(); I += N) 138 Elts.insert(Set[I]); 139 } 140}; 141 142// (sequence "Format", From, To) Generate a sequence of records by name. 143struct SequenceOp : public SetTheory::Operator { 144 void apply(SetTheory &ST, const DagInit *Expr, RecSet &Elts) { 145 if (Expr->arg_size() != 3) 146 throw "Bad args to (sequence \"Format\", From, To): " + 147 Expr->getAsString(); 148 std::string Format; 149 if (const StringInit *SI = dynamic_cast<const StringInit*>(Expr->arg_begin()[0])) 150 Format = SI->getValue(); 151 else 152 throw "Format must be a string: " + Expr->getAsString(); 153 154 int64_t From, To; 155 if (const IntInit *II = dynamic_cast<const IntInit*>(Expr->arg_begin()[1])) 156 From = II->getValue(); 157 else 158 throw "From must be an integer: " + Expr->getAsString(); 159 if (From < 0 || From >= (1 << 30)) 160 throw "From out of range"; 161 162 if (const IntInit *II = dynamic_cast<const IntInit*>(Expr->arg_begin()[2])) 163 To = II->getValue(); 164 else 165 throw "From must be an integer: " + Expr->getAsString(); 166 if (To < 0 || To >= (1 << 30)) 167 throw "To out of range"; 168 169 RecordKeeper &Records = 170 dynamic_cast<const DefInit&>(*Expr->getOperator()).getDef()->getRecords(); 171 172 int Step = From <= To ? 1 : -1; 173 for (To += Step; From != To; From += Step) { 174 std::string Name; 175 raw_string_ostream OS(Name); 176 OS << format(Format.c_str(), unsigned(From)); 177 Record *Rec = Records.getDef(OS.str()); 178 if (!Rec) 179 throw "No def named '" + Name + "': " + Expr->getAsString(); 180 // Try to reevaluate Rec in case it is a set. 181 if (const RecVec *Result = ST.expand(Rec)) 182 Elts.insert(Result->begin(), Result->end()); 183 else 184 Elts.insert(Rec); 185 } 186 } 187}; 188 189// Expand a Def into a set by evaluating one of its fields. 190struct FieldExpander : public SetTheory::Expander { 191 StringRef FieldName; 192 193 FieldExpander(StringRef fn) : FieldName(fn) {} 194 195 void expand(SetTheory &ST, Record *Def, RecSet &Elts) { 196 ST.evaluate(Def->getValueInit(FieldName), Elts); 197 } 198}; 199} // end anonymous namespace 200 201SetTheory::SetTheory() { 202 addOperator("add", new AddOp); 203 addOperator("sub", new SubOp); 204 addOperator("and", new AndOp); 205 addOperator("shl", new ShlOp); 206 addOperator("trunc", new TruncOp); 207 addOperator("rotl", new RotOp(false)); 208 addOperator("rotr", new RotOp(true)); 209 addOperator("decimate", new DecimateOp); 210 addOperator("sequence", new SequenceOp); 211} 212 213void SetTheory::addOperator(StringRef Name, Operator *Op) { 214 Operators[Name] = Op; 215} 216 217void SetTheory::addExpander(StringRef ClassName, Expander *E) { 218 Expanders[ClassName] = E; 219} 220 221void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { 222 addExpander(ClassName, new FieldExpander(FieldName)); 223} 224 225void SetTheory::evaluate(const Init *Expr, RecSet &Elts) { 226 // A def in a list can be a just an element, or it may expand. 227 if (const DefInit *Def = dynamic_cast<const DefInit*>(Expr)) { 228 if (const RecVec *Result = expand(Def->getDef())) 229 return Elts.insert(Result->begin(), Result->end()); 230 Elts.insert(Def->getDef()); 231 return; 232 } 233 234 // Lists simply expand. 235 if (const ListInit *LI = dynamic_cast<const ListInit*>(Expr)) 236 return evaluate(LI->begin(), LI->end(), Elts); 237 238 // Anything else must be a DAG. 239 const DagInit *DagExpr = dynamic_cast<const DagInit*>(Expr); 240 if (!DagExpr) 241 throw "Invalid set element: " + Expr->getAsString(); 242 const DefInit *OpInit = dynamic_cast<const DefInit*>(DagExpr->getOperator()); 243 if (!OpInit) 244 throw "Bad set expression: " + Expr->getAsString(); 245 Operator *Op = Operators.lookup(OpInit->getDef()->getName()); 246 if (!Op) 247 throw "Unknown set operator: " + Expr->getAsString(); 248 Op->apply(*this, DagExpr, Elts); 249} 250 251const RecVec *SetTheory::expand(Record *Set) { 252 // Check existing entries for Set and return early. 253 ExpandMap::iterator I = Expansions.find(Set); 254 if (I != Expansions.end()) 255 return &I->second; 256 257 // This is the first time we see Set. Find a suitable expander. 258 try { 259 const std::vector<Record*> &SC = Set->getSuperClasses(); 260 for (unsigned i = 0, e = SC.size(); i != e; ++i) 261 if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { 262 // This breaks recursive definitions. 263 RecVec &EltVec = Expansions[Set]; 264 RecSet Elts; 265 Exp->expand(*this, Set, Elts); 266 EltVec.assign(Elts.begin(), Elts.end()); 267 return &EltVec; 268 } 269 } catch (const std::string &Error) { 270 throw TGError(Set->getLoc(), Error); 271 } 272 273 // Set is not expandable. 274 return 0; 275} 276 277