summaryrefslogtreecommitdiff
path: root/src/jit/ssarenamestate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/ssarenamestate.cpp')
-rw-r--r--src/jit/ssarenamestate.cpp244
1 files changed, 244 insertions, 0 deletions
diff --git a/src/jit/ssarenamestate.cpp b/src/jit/ssarenamestate.cpp
new file mode 100644
index 0000000000..a1e05f192f
--- /dev/null
+++ b/src/jit/ssarenamestate.cpp
@@ -0,0 +1,244 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// ==++==
+//
+
+//
+
+//
+// ==--==
+
+/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XX XX
+XX SSA XX
+XX XX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+*/
+
+#include "jitpch.h"
+#include "ssaconfig.h"
+#include "ssarenamestate.h"
+
+/**
+ * Constructor - initialize the stacks and counters maps (lclVar -> stack/counter) map.
+ *
+ * @params alloc The allocator class used to allocate jitstd data.
+ */
+SsaRenameState::SsaRenameState(const jitstd::allocator<int>& alloc, unsigned lvaCount)
+ : counts(nullptr)
+ , stacks(nullptr)
+ , definedLocs(alloc)
+ , heapStack(alloc)
+ , heapCount(0)
+ , lvaCount(lvaCount)
+ , m_alloc(alloc)
+{
+}
+
+/**
+ * Allocates memory to hold SSA variable def counts,
+ * if not allocated already.
+ *
+ */
+void SsaRenameState::EnsureCounts()
+{
+ if (counts == nullptr)
+ {
+ counts = jitstd::utility::allocate<unsigned>(m_alloc, lvaCount);
+ for (unsigned i = 0; i < lvaCount; ++i)
+ {
+ counts[i] = SsaConfig::FIRST_SSA_NUM;
+ }
+ }
+}
+
+/**
+ * Allocates memory for holding pointers to lcl's stacks,
+ * if not allocated already.
+ *
+ */
+void SsaRenameState::EnsureStacks()
+{
+ if (stacks == nullptr)
+ {
+ stacks = jitstd::utility::allocate<Stack*>(m_alloc, lvaCount);
+ for (unsigned i = 0; i < lvaCount; ++i)
+ {
+ stacks[i] = nullptr;
+ }
+ }
+}
+
+/**
+ * Returns a SSA count number for a local variable and does a post increment.
+ *
+ * If there is no counter for the local yet, initializes it with the default value
+ * else, returns the count with a post increment, so the next def gets a new count.
+ *
+ * @params lclNum The local variable def for which a count has to be returned.
+ * @return the variable name for the current definition.
+ *
+ */
+unsigned SsaRenameState::CountForDef(unsigned lclNum)
+{
+ EnsureCounts();
+ unsigned count = counts[lclNum];
+ counts[lclNum]++;
+ DBG_SSA_JITDUMP("Incrementing counter = %d by 1 for V%02u.\n", count, lclNum);
+ return count;
+}
+
+/**
+ * Returns a SSA count number for a local variable from top of the stack.
+ *
+ * @params lclNum The local variable def for which a count has to be returned.
+ * @return the current variable name for the "use".
+ *
+ * @remarks If the stack is empty, then we have an use before a def. To handle this
+ * special case, we need to initialize the count with 'default+1', so the
+ * next definition will always use 'default+1' but return 'default' for
+ * all uses until a definition.
+ *
+ */
+unsigned SsaRenameState::CountForUse(unsigned lclNum)
+{
+ EnsureStacks();
+ DBG_SSA_JITDUMP("[SsaRenameState::CountForUse] V%02u\n", lclNum);
+
+ Stack* stack = stacks[lclNum];
+ if (stack == nullptr || stack->empty())
+ {
+ return SsaConfig::UNINIT_SSA_NUM;
+ }
+ return stack->back().m_count;
+}
+
+/**
+ * Pushes a count value on the variable stack.
+ *
+ * @params lclNum The local variable def whose stack the count needs to be pushed onto.
+ * @params count The current count value that needs to be pushed on to the stack.
+ *
+ * @remarks Usually called when renaming a "def."
+ * Create stack lazily when needed for the first time.
+ */
+void SsaRenameState::Push(BasicBlock* bb, unsigned lclNum, unsigned count)
+{
+ EnsureStacks();
+
+ // We'll use BB00 here to indicate the "block before any real blocks..."
+ DBG_SSA_JITDUMP("[SsaRenameState::Push] BB%02u, V%02u, count = %d\n", bb != nullptr ? bb->bbNum : 0, lclNum, count);
+
+ Stack* stack = stacks[lclNum];
+
+ if (stack == nullptr)
+ {
+ DBG_SSA_JITDUMP("\tCreating a new stack\n");
+ stack = stacks[lclNum] = new (jitstd::utility::allocate<Stack>(m_alloc), jitstd::placement_t()) Stack(m_alloc);
+ }
+
+ if (stack->empty() || stack->back().m_bb != bb)
+ {
+ stack->push_back(SsaRenameStateForBlock(bb, count));
+ // Remember that we've pushed a def for this loc (so we don't have
+ // to traverse *all* the locs to do the necessary pops later).
+ definedLocs.push_back(SsaRenameStateLocDef(bb, lclNum));
+ }
+ else
+ {
+ stack->back().m_count = count;
+ }
+
+#ifdef DEBUG
+ if (JitTls::GetCompiler()->verboseSsa)
+ {
+ printf("\tContents of the stack: [");
+ for (Stack::iterator iter2 = stack->begin(); iter2 != stack->end(); iter2++)
+ {
+ printf("<BB%02u, %d>", ((*iter2).m_bb != nullptr ? (*iter2).m_bb->bbNum : 0), (*iter2).m_count);
+ }
+ printf("]\n");
+
+ DumpStacks();
+ }
+#endif
+}
+
+void SsaRenameState::PopBlockStacks(BasicBlock* block)
+{
+ DBG_SSA_JITDUMP("[SsaRenameState::PopBlockStacks] BB%02u\n", block->bbNum);
+ // Iterate over the stacks for all the variables, popping those that have an entry
+ // for "block" on top.
+ while (!definedLocs.empty() && definedLocs.back().m_bb == block)
+ {
+ unsigned lclNum = definedLocs.back().m_lclNum;
+ assert(stacks != nullptr); // Cannot be empty because definedLocs is not empty.
+ Stack* stack = stacks[lclNum];
+ assert(stack != nullptr);
+ assert(stack->back().m_bb == block);
+ stack->pop_back();
+ definedLocs.pop_back();
+ }
+#ifdef DEBUG
+ // It should now be the case that no stack in stacks has an entry for "block" on top --
+ // the loop above popped them all.
+ for (unsigned i = 0; i < lvaCount; ++i)
+ {
+ if (stacks != nullptr && stacks[i] != nullptr && !stacks[i]->empty())
+ {
+ assert(stacks[i]->back().m_bb != block);
+ }
+ }
+ if (JitTls::GetCompiler()->verboseSsa)
+ {
+ DumpStacks();
+ }
+#endif // DEBUG
+}
+
+void SsaRenameState::PopBlockHeapStack(BasicBlock* block)
+{
+ while (heapStack.size() > 0 && heapStack.back().m_bb == block)
+ {
+ heapStack.pop_back();
+ }
+}
+
+#ifdef DEBUG
+/**
+ * Print the stack data for each variable in a loop.
+ */
+void SsaRenameState::DumpStacks()
+{
+ printf("Dumping stacks:\n-------------------------------\n");
+ if (lvaCount == 0)
+ {
+ printf("None\n");
+ }
+ else
+ {
+ EnsureStacks();
+ for (unsigned i = 0; i < lvaCount; ++i)
+ {
+ Stack* stack = stacks[i];
+ printf("V%02u:\t", i);
+ if (stack != nullptr)
+ {
+ for (Stack::iterator iter2 = stack->begin(); iter2 != stack->end(); ++iter2)
+ {
+ if (iter2 != stack->begin())
+ {
+ printf(", ");
+ }
+ printf("<BB%02u, %2d>", ((*iter2).m_bb != nullptr ? (*iter2).m_bb->bbNum : 0), (*iter2).m_count);
+ }
+ }
+ printf("\n");
+ }
+ }
+}
+#endif // DEBUG