[llvm] [NFC][SROA] Remove implementation details from SROA header (PR #72846)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 03:17:31 PST 2023
================
@@ -123,6 +125,140 @@ static cl::opt<bool> SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false),
cl::Hidden);
namespace {
+class AllocaSliceRewriter;
+class AllocaSlices;
+class Partition;
+class SROALegacyPass;
+
+class SelectHandSpeculativity {
+ unsigned char Storage = 0; // None are speculatable by default.
+ using TrueVal = Bitfield::Element<bool, 0, 1>; // Low 0'th bit.
+ using FalseVal = Bitfield::Element<bool, 1, 1>; // Low 1'th bit.
+public:
+ SelectHandSpeculativity() = default;
+ SelectHandSpeculativity &setAsSpeculatable(bool isTrueVal);
+ bool isSpeculatable(bool isTrueVal) const;
+ bool areAllSpeculatable() const;
+ bool areAnySpeculatable() const;
+ bool areNoneSpeculatable() const;
+ // For interop as int half of PointerIntPair.
+ explicit operator intptr_t() const { return static_cast<intptr_t>(Storage); }
+ explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
+};
+static_assert(sizeof(SelectHandSpeculativity) == sizeof(unsigned char));
+
+using PossiblySpeculatableLoad =
+ PointerIntPair<LoadInst *, 2, SelectHandSpeculativity>;
+using UnspeculatableStore = StoreInst *;
+using RewriteableMemOp =
+ std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
+using RewriteableMemOps = SmallVector<RewriteableMemOp, 2>;
+
+/// An optimization pass providing Scalar Replacement of Aggregates.
+///
+/// This pass takes allocations which can be completely analyzed (that is, they
+/// don't escape) and tries to turn them into scalar SSA values. There are
+/// a few steps to this process.
+///
+/// 1) It takes allocations of aggregates and analyzes the ways in which they
+/// are used to try to split them into smaller allocations, ideally of
+/// a single scalar data type. It will split up memcpy and memset accesses
+/// as necessary and try to isolate individual scalar accesses.
+/// 2) It will transform accesses into forms which are suitable for SSA value
+/// promotion. This can be replacing a memset with a scalar store of an
+/// integer value, or it can involve speculating operations on a PHI or
+/// select to be a PHI or select of the results.
+/// 3) Finally, this will try to detect a pattern of accesses which map cleanly
+/// onto insert and extract operations on a vector value, and convert them to
+/// this form. By doing so, it will enable promotion of vector aggregates to
+/// SSA vector values.
+class SROA {
+ LLVMContext *const C;
+ DomTreeUpdater *const DTU;
+ AssumptionCache *const AC;
+ const bool PreserveCFG;
+
+ /// Worklist of alloca instructions to simplify.
+ ///
+ /// Each alloca in the function is added to this. Each new alloca formed gets
+ /// added to it as well to recursively simplify unless that alloca can be
+ /// directly promoted. Finally, each time we rewrite a use of an alloca other
+ /// the one being actively rewritten, we add it back onto the list if not
+ /// already present to ensure it is re-visited.
+ SmallSetVector<AllocaInst *, 16> Worklist;
+
+ /// A collection of instructions to delete.
+ /// We try to batch deletions to simplify code and make things a bit more
+ /// efficient. We also make sure there is no dangling pointers.
+ SmallVector<WeakVH, 8> DeadInsts;
+
+ /// Post-promotion worklist.
+ ///
+ /// Sometimes we discover an alloca which has a high probability of becoming
+ /// viable for SROA after a round of promotion takes place. In those cases,
+ /// the alloca is enqueued here for re-processing.
+ ///
+ /// Note that we have to be very careful to clear allocas out of this list in
+ /// the event they are deleted.
+ SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
+
+ /// A collection of alloca instructions we can directly promote.
+ std::vector<AllocaInst *> PromotableAllocas;
+
+ /// A worklist of PHIs to speculate prior to promoting allocas.
+ ///
+ /// All of these PHIs have been checked for the safety of speculation and by
+ /// being speculated will allow promoting allocas currently in the promotable
+ /// queue.
+ SmallSetVector<PHINode *, 8> SpeculatablePHIs;
+
+ /// A worklist of select instructions to rewrite prior to promoting
+ /// allocas.
+ SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
+
+ /// Select instructions that use an alloca and are subsequently loaded can be
+ /// rewritten to load both input pointers and then select between the result,
+ /// allowing the load of the alloca to be promoted.
+ /// From this:
+ /// %P2 = select i1 %cond, ptr %Alloca, ptr %Other
+ /// %V = load <type>, ptr %P2
+ /// to:
+ /// %V1 = load <type>, ptr %Alloca -> will be mem2reg'd
+ /// %V2 = load <type>, ptr %Other
+ /// %V = select i1 %cond, <type> %V1, <type> %V2
+ ///
+ /// We can do this to a select if its only uses are loads
+ /// and if either the operand to the select can be loaded unconditionally,
+ /// or if we are allowed to perform CFG modifications.
+ /// If found an intervening bitcast with a single use of the load,
+ /// allow the promotion.
+ static std::optional<RewriteableMemOps>
+ isSafeSelectToSpeculate(SelectInst &SI, bool PreserveCFG);
+
+public:
+ SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
+ SROAOptions PreserveCFG_)
+ : C(C), DTU(DTU), AC(AC),
+ PreserveCFG(PreserveCFG_ == SROAOptions::PreserveCFG) {}
+
+ /// Helper used by both the SROAPass and by the legacy pass.
+ std::pair<bool /*Changed*/, bool /*CFGChanged*/> runSROA(Function &F);
+
+private:
+ friend class AllocaSliceRewriter;
+ friend class SROALegacyPass;
----------------
nikic wrote:
Why do we need this friend class?
https://github.com/llvm/llvm-project/pull/72846
More information about the llvm-commits
mailing list