diff --git a/llvm/lib/Target/EVM/EVMHelperUtilities.h b/llvm/lib/Target/EVM/EVMHelperUtilities.h index 2ff5849f493a..27c9ff54999d 100644 --- a/llvm/lib/Target/EVM/EVMHelperUtilities.h +++ b/llvm/lib/Target/EVM/EVMHelperUtilities.h @@ -15,14 +15,13 @@ #ifndef LLVM_LIB_TARGET_EVM_EVMHELPERUTILITIES_H #define LLVM_LIB_TARGET_EVM_EVMHELPERUTILITIES_H +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" -#include -#include -#include +#include #include #include -#include namespace llvm { @@ -33,90 +32,32 @@ template struct Overload : Ts... { }; template Overload(Ts...) -> Overload; -template static inline SmallVector iota17(T begin, T end) { - SmallVector R(end - begin); - std::iota(R.begin(), R.end(), begin); - return R; -} - -/// Concatenate the contents of a container into a vector -template -std::vector &operator+=(std::vector &lhs, U &rhs) { - for (auto const &elm : rhs) - lhs.push_back(T(elm)); - return lhs; -} - -template -std::vector &operator+=(std::vector &lhs, U &&rhs) { - std::move(rhs.begin(), rhs.end(), std::back_inserter(lhs)); - return lhs; -} - -/// Concatenate two vectors of elements. -template -inline std::vector operator+(std::vector const &lhs, - std::vector const &rhs) { - std::vector result(lhs); - result += rhs; - return result; -} - -/// Concatenate two vectors of elements, moving them. -template -inline std::vector operator+(std::vector &&lhs, std::vector &&rhs) { - std::vector result(std::move(lhs)); - assert(&lhs != &rhs); - result += std::move(rhs); - return result; -} - namespace EVMUtils { - bool callWillReturn(const MachineInstr *Call); -template bool contains(const T &t, const V &v) { - return std::end(t) != std::find(std::begin(t), std::end(t), v); +/// Return a vector, containing sequentially increasing values from \p Begin +/// to \p End. +template static inline SmallVector iota(T Begin, T End) { + SmallVector R(End - Begin); + std::iota(R.begin(), R.end(), Begin); + return R; } +/// Return the number of hops from the beginning of the \p RangeOrContainer +/// to the \p Item. If no \p Item is found in the \p RangeOrContainer, +/// std::nullopt is returned. template -std::optional findOffset(T &&t, V &&v) { - auto begin = std::begin(t); - auto end = std::end(t); - auto it = std::find(begin, end, std::forward(v)); - if (it == end) - return std::nullopt; - return std::distance(begin, it); -} - -template -auto take_last(T &&t, size_t N) -> iterator_range { - auto it = t.end(); - std::advance(it, -N); - return make_range(it, t.end()); -} - -template -auto drop_first(T &&t, size_t N) -> iterator_range { - auto it = t.begin(); - std::advance(it, N); - return make_range(it, t.end()); -} - -template -iterator_range get_reverse(const T &t) { - return llvm::make_range(t.rbegin(), t.rend()); -} - -template auto to_vector(R &&r) { - std::vector v; - v.assign(r.begin(), r.end()); - return v; +std::optional offset(T &&RangeOrContainer, V &&Item) { + auto It = find(RangeOrContainer, Item); + return (It == adl_end(RangeOrContainer)) + ? std::nullopt + : std::optional(std::distance(adl_begin(RangeOrContainer), It)); } -template void emplace_back_unique(T &t, V &&v) { - if (t.end() == std::find(t.begin(), t.end(), v)) - t.emplace_back(v); +/// Return a range covering the last N elements of \p RangeOrContainer. +template auto take_back(T &&RangeOrContainer, size_t N = 1) { + return make_range(std::prev(adl_end(RangeOrContainer), N), + adl_end(RangeOrContainer)); } /// Generic breadth first search. @@ -159,8 +100,8 @@ template struct BreadthFirstSearch { void abort() { verticesToTraverse.clear(); } - std::list verticesToTraverse; - std::set visited{}; + std::deque verticesToTraverse; + DenseSet visited{}; }; } // namespace EVMUtils diff --git a/llvm/lib/Target/EVM/EVMStackDebug.cpp b/llvm/lib/Target/EVM/EVMStackDebug.cpp index d91a04627580..0752c768c9df 100644 --- a/llvm/lib/Target/EVM/EVMStackDebug.cpp +++ b/llvm/lib/Target/EVM/EVMStackDebug.cpp @@ -130,7 +130,7 @@ void StackLayoutPrinter::printBlock(MachineBasicBlock const &Block) { assert(Operation.Input.size() <= EntryLayout.size()); for (size_t i = 0; i < Operation.Input.size(); ++i) EntryLayout.pop_back(); - EntryLayout += Operation.Output; + EntryLayout.append(Operation.Output); OS << stackToString(EntryLayout) << "\n"; } OS << "\n"; diff --git a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp index 634fbc419a15..b5e5961e65da 100644 --- a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp +++ b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp @@ -34,16 +34,16 @@ using namespace llvm; namespace { /// Returns all stack too deep errors that would occur when shuffling \p Source /// to \p Target. -std::vector +SmallVector findStackTooDeep(Stack const &Source, Stack const &Target) { Stack CurrentStack = Source; - std::vector Errors; + SmallVector Errors; auto getVariableChoices = [](auto &&SlotRange) { - std::vector Result; + SmallVector Result; for (auto const &Slot : SlotRange) if (auto const *VarSlot = std::get_if(&Slot)) - if (!EVMUtils::contains(Result, VarSlot->VirtualReg)) + if (!is_contained(Result, VarSlot->VirtualReg)) Result.push_back(VarSlot->VirtualReg); return Result; }; @@ -54,18 +54,17 @@ findStackTooDeep(Stack const &Source, Stack const &Target) { if (I > 16) Errors.emplace_back(EVMStackLayoutGenerator::StackTooDeep{ I - 16, - getVariableChoices(EVMUtils::take_last(CurrentStack, I + 1))}); + getVariableChoices(EVMUtils::take_back(CurrentStack, I + 1))}); }, [&](StackSlot const &Slot) { if (isRematerializable(Slot)) return; - if (auto depth = - EVMUtils::findOffset(EVMUtils::get_reverse(CurrentStack), Slot); - depth && *depth >= 16) + if (auto Depth = EVMUtils::offset(reverse(CurrentStack), Slot); + Depth && *Depth >= 16) Errors.emplace_back(EVMStackLayoutGenerator::StackTooDeep{ - *depth - 15, getVariableChoices( - EVMUtils::take_last(CurrentStack, *depth + 1))}); + *Depth - 15, getVariableChoices( + EVMUtils::take_back(CurrentStack, *Depth + 1))}); }, [&]() {}); return Errors; @@ -82,7 +81,7 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, struct PreviousSlot { size_t slot; }; - using LayoutT = std::vector>; + using LayoutT = SmallVector>; // Determine the number of slots that have to be on stack before executing the // operation (excluding the inputs of the operation itself). That is slots @@ -90,7 +89,7 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, // operation. size_t PreOperationLayoutSize = Post.size(); for (auto const &Slot : Post) - if (EVMUtils::contains(OperationOutput, Slot) || GenerateSlotOnTheFly(Slot)) + if (is_contained(OperationOutput, Slot) || GenerateSlotOnTheFly(Slot)) --PreOperationLayoutSize; // The symbolic layout directly after the operation has the form @@ -98,7 +97,7 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, LayoutT Layout; for (size_t Index = 0; Index < PreOperationLayoutSize; ++Index) Layout.emplace_back(PreviousSlot{Index}); - Layout += OperationOutput; + Layout.append(OperationOutput.begin(), OperationOutput.end()); // Shortcut for trivial case. if (Layout.empty()) @@ -131,16 +130,15 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, bool isCompatible(size_t Source, size_t Target) { return Source < Layout.size() && Target < Post.size() && - (std::holds_alternative(Post.at(Target)) || + (std::holds_alternative(Post[Target]) || std::visit(Overload{[&](const PreviousSlot &) { - return !Outputs.count(Post.at(Target)) && - !GenerateSlotOnTheFly( - Post.at(Target)); + return !Outputs.count(Post[Target]) && + !GenerateSlotOnTheFly(Post[Target]); }, [&](const StackSlot &S) { - return S == Post.at(Target); + return S == Post[Target]; }}, - Layout.at(Source))); + Layout[Source])); } bool sourceIsSame(size_t Lhs, size_t Rhs) { @@ -151,33 +149,32 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, return Lhs == Rhs; }, [&](auto const &, auto const &) { return false; }}, - Layout.at(Lhs), Layout.at(Rhs)); + Layout[Lhs], Layout[Rhs]); } int sourceMultiplicity(size_t Offset) { return std::visit( Overload{[&](PreviousSlot const &) { return 0; }, [&](StackSlot const &S) { return Mult.at(S); }}, - Layout.at(Offset)); + Layout[Offset]); } int targetMultiplicity(size_t Offset) { - if (!Outputs.count(Post.at(Offset)) && - !GenerateSlotOnTheFly(Post.at(Offset))) + if (!Outputs.count(Post[Offset]) && !GenerateSlotOnTheFly(Post[Offset])) return 0; - return Mult.at(Post.at(Offset)); + return Mult.at(Post[Offset]); } bool targetIsArbitrary(size_t Offset) { return Offset < Post.size() && - std::holds_alternative(Post.at(Offset)); + std::holds_alternative(Post[Offset]); } void swap(size_t I) { assert(!std::holds_alternative( - Layout.at(Layout.size() - I - 1)) || + Layout[Layout.size() - I - 1]) || !std::holds_alternative(Layout.back())); - std::swap(Layout.at(Layout.size() - I - 1), Layout.back()); + std::swap(Layout[Layout.size() - I - 1], Layout.back()); } size_t sourceSize() { return Layout.size(); } @@ -186,7 +183,7 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, void pop() { Layout.pop_back(); } - void pushOrDupTarget(size_t Offset) { Layout.push_back(Post.at(Offset)); } + void pushOrDupTarget(size_t Offset) { Layout.push_back(Post[Offset]); } }; Shuffler::shuffle(Layout, Post, GenerateSlotOnTheFly); @@ -199,12 +196,12 @@ Stack createIdealLayout(const Stack &OperationOutput, const Stack &Post, // VariableSlot{"tmp"}, then we want the variable tmp in the slot at offset 2 // in the layout before the operation. assert(Layout.size() == Post.size()); - std::vector> IdealLayout(Post.size(), std::nullopt); + SmallVector> IdealLayout(Post.size(), std::nullopt); for (unsigned Idx = 0; Idx < std::min(Layout.size(), Post.size()); ++Idx) { auto &Slot = Post[Idx]; auto &IdealPosition = Layout[Idx]; if (PreviousSlot *PrevSlot = std::get_if(&IdealPosition)) - IdealLayout.at(PrevSlot->slot) = Slot; + IdealLayout[PrevSlot->slot] = Slot; } // The tail of layout must have contained the operation outputs and will not @@ -268,11 +265,11 @@ Stack EVMStackLayoutGenerator::propagateStackThroughOperation( if (auto const *Assign = std::get_if(&Operation.Operation)) for (auto &StackSlot : IdealStack) if (auto const *VarSlot = std::get_if(&StackSlot)) - assert(!EVMUtils::contains(Assign->Variables, *VarSlot)); + assert(!is_contained(Assign->Variables, *VarSlot)); // Since stack+Operation.output can be easily shuffled to ExitLayout, the // desired layout before the operation is stack+Operation.input; - IdealStack += Operation.Input; + IdealStack.append(Operation.Input); // Store the exact desired operation entry layout. The stored layout will be // recreated by the code transform before executing the operation. However, @@ -286,9 +283,8 @@ Stack EVMStackLayoutGenerator::propagateStackThroughOperation( while (!IdealStack.empty()) { if (isRematerializable(IdealStack.back())) IdealStack.pop_back(); - else if (auto Offset = EVMUtils::findOffset( - EVMUtils::drop_first(EVMUtils::get_reverse(IdealStack), 1), - IdealStack.back())) { + else if (auto Offset = EVMUtils::offset(drop_begin(reverse(IdealStack), 1), + IdealStack.back())) { if (*Offset + 2 < 16) IdealStack.pop_back(); else @@ -304,10 +300,8 @@ Stack EVMStackLayoutGenerator::propagateStackThroughBlock( Stack ExitStack, const MachineBasicBlock *Block, bool AggressiveStackCompression) { Stack CurrentStack = ExitStack; - const std::vector &Operations = StackModel.getOperations(Block); - auto I = Operations.crbegin(), E = Operations.crend(); - for (; I != E; ++I) { - Stack NewStack = propagateStackThroughOperation(CurrentStack, *I, + for (const Operation &Op : reverse(StackModel.getOperations(Block))) { + Stack NewStack = propagateStackThroughOperation(CurrentStack, Op, AggressiveStackCompression); if (!AggressiveStackCompression && !findStackTooDeep(NewStack, CurrentStack).empty()) @@ -359,8 +353,7 @@ void EVMStackLayoutGenerator::processEntryPoint( auto B = EntryLayout.begin(), E = EntryLayout.end(); const Stack &ExitLayout = MBBExitLayoutMap[JumpingBlock]; if (std::any_of(B, E, [ExitLayout](const StackSlot &Slot) { - return std::find(ExitLayout.begin(), ExitLayout.end(), Slot) == - ExitLayout.end(); + return find(ExitLayout, Slot) == ExitLayout.end(); })) { // In particular we can visit backwards starting from 'JumpingBlock' // and mark all entries to-be-visited again until we hit 'Target'. @@ -403,7 +396,7 @@ void EVMStackLayoutGenerator::processEntryPoint( // Calling convention: input arguments are passed in stack such that the // first one specified in the function declaration is passed on the stack TOP. - EntryStack += StackModel.getFunctionParameters(); + EntryStack.append(StackModel.getFunctionParameters()); std::reverse(IsNoReturn ? EntryStack.begin() : std::next(EntryStack.begin()), EntryStack.end()); MBBEntryLayoutMap[Entry] = std::move(EntryStack); @@ -517,8 +510,7 @@ void EVMStackLayoutGenerator::stitchConditionalJumps( // Whatever the block being jumped to does not actually require, // can be marked as junk. for (StackSlot &Slot : NewEntryLayout) { - if (std::find(OriginalEntryLayout.begin(), OriginalEntryLayout.end(), - Slot) == OriginalEntryLayout.end()) + if (find(OriginalEntryLayout, Slot) == OriginalEntryLayout.end()) Slot = JunkSlot{}; } #ifndef NDEBUG @@ -526,8 +518,7 @@ void EVMStackLayoutGenerator::stitchConditionalJumps( // actually present or can be generated. for (StackSlot const &Slot : OriginalEntryLayout) assert(isRematerializable(Slot) || - std::find(NewEntryLayout.begin(), NewEntryLayout.end(), - Slot) != NewEntryLayout.end()); + find(NewEntryLayout, Slot) != NewEntryLayout.end()); #endif // NDEBUG return NewEntryLayout; }; @@ -558,25 +549,29 @@ Stack EVMStackLayoutGenerator::combineStack(Stack const &Stack1, } Stack Stack1Tail, Stack2Tail; - for (auto Slot : EVMUtils::drop_first(Stack1, CommonPrefix.size())) + for (const auto &Slot : drop_begin(Stack1, CommonPrefix.size())) Stack1Tail.emplace_back(Slot); - for (auto Slot : EVMUtils::drop_first(Stack2, CommonPrefix.size())) + for (const auto &Slot : drop_begin(Stack2, CommonPrefix.size())) Stack2Tail.emplace_back(Slot); - if (Stack1Tail.empty()) - return CommonPrefix + compressStack(Stack2Tail); + if (Stack1Tail.empty()) { + CommonPrefix.append(compressStack(Stack2Tail)); + return CommonPrefix; + } - if (Stack2Tail.empty()) - return CommonPrefix + compressStack(Stack1Tail); + if (Stack2Tail.empty()) { + CommonPrefix.append(compressStack(Stack1Tail)); + return CommonPrefix; + } Stack Candidate; for (auto Slot : Stack1Tail) - if (!EVMUtils::contains(Candidate, Slot)) + if (!is_contained(Candidate, Slot)) Candidate.emplace_back(Slot); for (auto Slot : Stack2Tail) - if (!EVMUtils::contains(Candidate, Slot)) + if (!is_contained(Candidate, Slot)) Candidate.emplace_back(Slot); { @@ -603,8 +598,8 @@ Stack EVMStackLayoutGenerator::combineStack(Stack const &Stack1, return; Stack Tmp = CommonPrefix; - Tmp += TestStack; - auto Depth = EVMUtils::findOffset(EVMUtils::get_reverse(Tmp), Slot); + Tmp.append(TestStack); + auto Depth = EVMUtils::offset(reverse(Tmp), Slot); if (Depth && *Depth >= 16) NumOps += 1000; }; @@ -618,7 +613,7 @@ Stack EVMStackLayoutGenerator::combineStack(Stack const &Stack1, size_t N = Candidate.size(); Stack BestCandidate = Candidate; size_t BestCost = evaluate(Candidate); - std::vector C(N, 0); + SmallVector C(N, 0); size_t I = 1; while (I < N) { if (C[I] < I) { @@ -644,7 +639,8 @@ Stack EVMStackLayoutGenerator::combineStack(Stack const &Stack1, } } - return CommonPrefix + BestCandidate; + CommonPrefix.append(BestCandidate); + return CommonPrefix; } Stack EVMStackLayoutGenerator::compressStack(Stack CurStack) { @@ -652,7 +648,7 @@ Stack EVMStackLayoutGenerator::compressStack(Stack CurStack) { do { if (FirstDupOffset) { if (*FirstDupOffset != (CurStack.size() - 1)) - std::swap(CurStack.at(*FirstDupOffset), CurStack.back()); + std::swap(CurStack[*FirstDupOffset], CurStack.back()); CurStack.pop_back(); FirstDupOffset.reset(); } @@ -665,9 +661,8 @@ Stack EVMStackLayoutGenerator::compressStack(Stack CurStack) { break; } - if (auto DupDepth = EVMUtils::findOffset( - EVMUtils::drop_first(EVMUtils::get_reverse(CurStack), Depth + 1), - Slot)) { + if (auto DupDepth = EVMUtils::offset( + drop_begin(reverse(CurStack), Depth + 1), Slot)) { if (Depth + *DupDepth <= 16) { FirstDupOffset = CurStack.size() - Depth - 1; break; @@ -693,7 +688,7 @@ size_t llvm::EvaluateStackTransform(Stack Source, Stack const &Target) { if (isRematerializable(Slot)) OpGas += 3; else { - auto Depth = EVMUtils::findOffset(EVMUtils::get_reverse(Source), Slot); + auto Depth = EVMUtils::offset(reverse(Source), Slot); if (!Depth) llvm_unreachable("No slot in the stack"); @@ -717,17 +712,19 @@ void EVMStackLayoutGenerator::fillInJunk(const MachineBasicBlock *Block) { EVMUtils::BreadthFirstSearch BFS{{Entry}}; BFS.run([&](const MachineBasicBlock *Block, auto VisitSucc) { - const Stack &EntryLayout = MBBEntryLayoutMap.at(Block); - MBBEntryLayoutMap[Block] = Stack(NumJunk, JunkSlot{}) + EntryLayout; + Stack EntryTmp(NumJunk, JunkSlot{}); + EntryTmp.append(MBBEntryLayoutMap.at(Block)); + MBBEntryLayoutMap[Block] = std::move(EntryTmp); for (const Operation &Operation : StackModel.getOperations(Block)) { - const Stack &OpEntryLayout = OperationEntryLayoutMap.at(&Operation); - OperationEntryLayoutMap[&Operation] = - Stack(NumJunk, JunkSlot{}) + OpEntryLayout; + Stack OpEntryTmp(NumJunk, JunkSlot{}); + OpEntryTmp.append(OperationEntryLayoutMap.at(&Operation)); + OperationEntryLayoutMap[&Operation] = std::move(OpEntryTmp); } - const Stack &ExitLayout = MBBExitLayoutMap.at(Block); - MBBExitLayoutMap[Block] = Stack(NumJunk, JunkSlot{}) + ExitLayout; + Stack ExitTmp(NumJunk, JunkSlot{}); + ExitTmp.append(MBBExitLayoutMap.at(Block)); + MBBExitLayoutMap[Block] = std::move(ExitTmp); for (const MachineBasicBlock *Succ : Block->successors()) VisitSucc(Succ); @@ -742,8 +739,9 @@ void EVMStackLayoutGenerator::fillInJunk(const MachineBasicBlock *Block) { size_t BestNumJunk = 0; size_t MaxJunk = EntryLayout.size(); for (size_t NumJunk = 1; NumJunk <= MaxJunk; ++NumJunk) { - size_t Cost = EvaluateStackTransform( - EntryLayout, Stack{NumJunk, JunkSlot{}} + TargetLayout); + Stack JunkedTarget(NumJunk, JunkSlot{}); + JunkedTarget.append(TargetLayout); + size_t Cost = EvaluateStackTransform(EntryLayout, JunkedTarget); if (Cost < BestCost) { BestCost = Cost; BestNumJunk = NumJunk; @@ -770,7 +768,7 @@ void EVMStackLayoutGenerator::fillInJunk(const MachineBasicBlock *Block) { !CFGInfo.isOnPathToFuncReturn(Block)) { const Stack EntryLayout = MBBEntryLayoutMap.at(Block); const Stack &ExitLayout = MBBExitLayoutMap.at(Block); - const std::vector &Ops = StackModel.getOperations(Block); + const SmallVector &Ops = StackModel.getOperations(Block); Stack const &NextLayout = Ops.empty() ? ExitLayout : OperationEntryLayoutMap.at(&Ops.front()); diff --git a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.h b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.h index 75ddafce9eae..8230e2f1bb16 100644 --- a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.h +++ b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.h @@ -66,7 +66,7 @@ class EVMStackLayoutGenerator { /// Number of slots that need to be saved. size_t deficit = 0; /// Set of variables, eliminating which would decrease the stack deficit. - std::vector variableChoices; + SmallVector variableChoices; }; EVMStackLayoutGenerator(const MachineFunction &MF, @@ -123,7 +123,7 @@ class EVMStackLayoutGenerator { /// Walks through the CFG and reports any stack too deep errors that would /// occur when generating code for it without countermeasures. - std::vector + SmallVector reportStackTooDeep(const MachineBasicBlock &Entry) const; /// Returns a copy of \p Stack stripped of all duplicates and slots that can diff --git a/llvm/lib/Target/EVM/EVMStackModel.cpp b/llvm/lib/Target/EVM/EVMStackModel.cpp index c288896d3ec8..ee868814ffb3 100644 --- a/llvm/lib/Target/EVM/EVMStackModel.cpp +++ b/llvm/lib/Target/EVM/EVMStackModel.cpp @@ -24,7 +24,7 @@ using namespace llvm; EVMStackModel::EVMStackModel(MachineFunction &MF, const LiveIntervals &LIS) : MF(MF), LIS(LIS) { for (MachineBasicBlock &MBB : MF) { - std::vector Ops; + SmallVector Ops; for (MachineInstr &MI : MBB) createOperation(MI, Ops); OperationsMap[&MBB] = std::move(Ops); @@ -33,7 +33,7 @@ EVMStackModel::EVMStackModel(MachineFunction &MF, const LiveIntervals &LIS) Stack EVMStackModel::getFunctionParameters() const { auto *MFI = MF.getInfo(); - std::vector Parameters(MFI->getNumParams(), JunkSlot{}); + SmallVector Parameters(MFI->getNumParams(), JunkSlot{}); for (const MachineInstr &MI : MF.front()) { if (MI.getOpcode() == EVM::ARGUMENT) { int64_t ArgIdx = MI.getOperand(1).getImm(); @@ -92,7 +92,7 @@ Stack EVMStackModel::getInstrOutput(const MachineInstr &MI) const { } void EVMStackModel::createOperation(MachineInstr &MI, - std::vector &Ops) const { + SmallVector &Ops) const { unsigned Opc = MI.getOpcode(); switch (Opc) { case EVM::STACK_LOAD: @@ -147,7 +147,7 @@ void EVMStackModel::createOperation(MachineInstr &MI, // Cretae CFG::Assignment object for the MI. Stack Input, Output; - std::vector Variables; + SmallVector Variables; switch (MI.getOpcode()) { case EVM::CONST_I256: { const Register DefReg = MI.getOperand(0).getReg(); diff --git a/llvm/lib/Target/EVM/EVMStackModel.h b/llvm/lib/Target/EVM/EVMStackModel.h index 08ddf2017ed1..1f5972821ff2 100644 --- a/llvm/lib/Target/EVM/EVMStackModel.h +++ b/llvm/lib/Target/EVM/EVMStackModel.h @@ -157,7 +157,7 @@ using StackSlot = JunkSlot>; /// The stack top is the last element of the vector. -using Stack = std::vector; +using Stack = SmallVector; /// Returns true if Slot can be materialized on the stack at any time. inline bool isRematerializable(const StackSlot &Slot) { @@ -181,7 +181,7 @@ struct Assignment { /// The variables being assigned to also occur as 'Output' in the /// 'Operation' containing the assignment, but are also stored here for /// convenience. - std::vector Variables; + SmallVector Variables; }; struct Operation { @@ -200,17 +200,17 @@ class EVMStackModel { Stack getInstrInput(const MachineInstr &MI) const; Stack getInstrOutput(const MachineInstr &MI) const; Stack getReturnArguments(const MachineInstr &MI) const; - const std::vector & + const SmallVector & getOperations(const MachineBasicBlock *MBB) const { return OperationsMap.at(MBB); } private: - void createOperation(MachineInstr &MI, std::vector &Ops) const; + void createOperation(MachineInstr &MI, SmallVector &Ops) const; MachineFunction &MF; const LiveIntervals &LIS; - std::map> OperationsMap; + DenseMap> OperationsMap; }; } // namespace llvm diff --git a/llvm/lib/Target/EVM/EVMStackShuffler.h b/llvm/lib/Target/EVM/EVMStackShuffler.h index 170426407974..6db0184bce9a 100644 --- a/llvm/lib/Target/EVM/EVMStackShuffler.h +++ b/llvm/lib/Target/EVM/EVMStackShuffler.h @@ -18,7 +18,6 @@ #include "EVMHelperUtilities.h" #include "EVMStackModel.h" -#include "llvm/CodeGen/MachineFunction.h" #include #include #include @@ -26,18 +25,6 @@ namespace llvm { -/* -template struct Overload : Ts... { -using Ts::operator()...; -}; -template Overload(Ts...) -> Overload; - -template static inline SmallVector iota17(T begin, T end) { -SmallVector R(end - begin); -std::iota(R.begin(), R.end(), begin); -return R; -} -*/ // Abstraction of stack shuffling operations. Can be defined as actual concept // once we switch to C++20. Used as an interface for the stack shuffler below. // The shuffle operation class is expected to internally keep track of a current @@ -164,7 +151,8 @@ class Shuffler { else if (Ops.sourceMultiplicity(SourceOffset) > 0) { // If this slot occurs again later, we skip this occurrence. // TODO: use C++ 20 ranges::views::iota - if (const auto &R = iota17(SourceOffset + 1, Ops.sourceSize()); + if (const auto &R = + EVMUtils::iota(SourceOffset + 1, Ops.sourceSize()); std::any_of(R.begin(), R.end(), [&](size_t Offset) { return Ops.sourceIsSame(SourceOffset, Offset); })) @@ -226,7 +214,7 @@ class Shuffler { ShuffleOperations Ops{std::forward(args)...}; // All source slots are final. - if (const auto &R = iota17(0u, Ops.sourceSize()); + if (const auto &R = EVMUtils::iota(0u, Ops.sourceSize()); std::all_of(R.begin(), R.end(), [&](size_t Index) { return Ops.isCompatible(Index, Index); })) { @@ -346,7 +334,8 @@ class Shuffler { (Ops.targetIsArbitrary(I) || Ops.targetMultiplicity(I) == 0)); assert(Ops.isCompatible(SourceTop, SourceTop)); - const auto &SwappableOffsets = iota17(Size > 17 ? Size - 17 : 0u, Size); + const auto &SwappableOffsets = + EVMUtils::iota(Size > 17 ? Size - 17 : 0u, Size); // If we find a lower slot that is out of position, but also compatible with // the top, swap that up. @@ -486,7 +475,7 @@ void createStackLayout(Stack &CurrentStack, Stack const &TargetStack, auto &Slot = targetStack[Offset]; if (std::holds_alternative(Slot) && Offset < currentStack.size()) - ++multiplicity[currentStack.at(Offset)]; + ++multiplicity[currentStack[Offset]]; else ++multiplicity[Slot]; } @@ -494,31 +483,30 @@ void createStackLayout(Stack &CurrentStack, Stack const &TargetStack, bool isCompatible(size_t Source, size_t Target) { return Source < currentStack.size() && Target < targetStack.size() && - (std::holds_alternative(targetStack.at(Target)) || - currentStack.at(Source) == targetStack.at(Target)); + (std::holds_alternative(targetStack[Target]) || + currentStack[Source] == targetStack[Target]); } bool sourceIsSame(size_t Lhs, size_t Rhs) { - return currentStack.at(Lhs) == currentStack.at(Rhs); + return currentStack[Lhs] == currentStack[Rhs]; } int sourceMultiplicity(size_t Offset) { - return multiplicity.at(currentStack.at(Offset)); + return multiplicity.at(currentStack[Offset]); } int targetMultiplicity(size_t Offset) { - return multiplicity.at(targetStack.at(Offset)); + return multiplicity.at(targetStack[Offset]); } bool targetIsArbitrary(size_t Offset) { return Offset < targetStack.size() && - std::holds_alternative(targetStack.at(Offset)); + std::holds_alternative(targetStack[Offset]); } void swap(size_t I) { swapCallback(static_cast(I)); - std::swap(currentStack.at(currentStack.size() - I - 1), - currentStack.back()); + std::swap(currentStack[currentStack.size() - I - 1], currentStack.back()); } size_t sourceSize() { return currentStack.size(); } @@ -531,7 +519,7 @@ void createStackLayout(Stack &CurrentStack, Stack const &TargetStack, } void pushOrDupTarget(size_t Offset) { - auto const &targetSlot = targetStack.at(Offset); + auto const &targetSlot = targetStack[Offset]; pushOrDupCallback(targetSlot); currentStack.push_back(targetSlot); } diff --git a/llvm/lib/Target/EVM/EVMStackifyCodeEmitter.cpp b/llvm/lib/Target/EVM/EVMStackifyCodeEmitter.cpp index ba3ae0151460..94f265587924 100644 --- a/llvm/lib/Target/EVM/EVMStackifyCodeEmitter.cpp +++ b/llvm/lib/Target/EVM/EVMStackifyCodeEmitter.cpp @@ -235,7 +235,7 @@ void EVMStackifyCodeEmitter::visitCall(const FunctionCall &Call) { if (EVMUtils::callWillReturn(Call.MI)) { [[maybe_unused]] const auto *returnLabelSlot = std::get_if( - &CurrentStack.at(CurrentStack.size() - NumArgs)); + &CurrentStack[CurrentStack.size() - NumArgs]); assert(returnLabelSlot && returnLabelSlot->Call == Call.MI); } @@ -313,8 +313,7 @@ void EVMStackifyCodeEmitter::createStackLayout(const Stack &TargetStack) { Emitter.emitSWAP(I); } else { int Deficit = static_cast(I) - 16; - const StackSlot &DeepSlot = - CurrentStack.at(CurrentStack.size() - I - 1); + const StackSlot &DeepSlot = CurrentStack[CurrentStack.size() - I - 1]; std::string VarNameDeep = SlotVariableName(DeepSlot); std::string VarNameTop = SlotVariableName(CurrentStack.back()); std::string Msg =