xref: /freebsd-src/contrib/llvm-project/llvm/lib/TableGen/SetTheory.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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