diff --git a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
index aa10aea07f..2f68c43f87 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
@@ -83,9 +83,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
             int intFreeRegisters = regMasks.IntAvailableRegisters;
             int vecFreeRegisters = regMasks.VecAvailableRegisters;
 
-            BlockInfo[] blockInfo = new BlockInfo[cfg.Blocks.Count];
+            var blockInfo = new BlockInfo[cfg.Blocks.Count];
 
-            List<LocalInfo> locInfo = new List<LocalInfo>();
+            var locInfo = new List<LocalInfo>();
+            var locVisited = new HashSet<Operand>();
 
             for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--)
             {
@@ -109,7 +110,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 
                         if (source.Kind == OperandKind.LocalVariable)
                         {
-                            locInfo[source.AsInt32() - 1].SetBlockIndex(block.Index);
+                            locInfo[source.GetLocalNumber() - 1].SetBlockIndex(block.Index);
                         }
                         else if (source.Kind == OperandKind.Memory)
                         {
@@ -117,12 +118,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 
                             if (memOp.BaseAddress != null)
                             {
-                                locInfo[memOp.BaseAddress.AsInt32() - 1].SetBlockIndex(block.Index);
+                                locInfo[memOp.BaseAddress.GetLocalNumber() - 1].SetBlockIndex(block.Index);
                             }
 
                             if (memOp.Index != null)
                             {
-                                locInfo[memOp.Index.AsInt32() - 1].SetBlockIndex(block.Index);
+                                locInfo[memOp.Index.GetLocalNumber() - 1].SetBlockIndex(block.Index);
                             }
                         }
                     }
@@ -135,9 +136,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
                         {
                             LocalInfo info;
 
-                            if (dest.Value != 0)
+                            if (!locVisited.Add(dest))
                             {
-                                info = locInfo[dest.AsInt32() - 1];
+                                info = locInfo[dest.GetLocalNumber() - 1];
                             }
                             else
                             {
@@ -198,7 +199,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 
                     void AllocateRegister(Operand source, MemoryOperand memOp, int srcIndex)
                     {
-                        LocalInfo info = locInfo[source.AsInt32() - 1];
+                        LocalInfo info = locInfo[source.GetLocalNumber() - 1];
 
                         info.UseCount++;
 
@@ -317,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
                             continue;
                         }
 
-                        LocalInfo info = locInfo[dest.AsInt32() - 1];
+                        LocalInfo info = locInfo[dest.GetLocalNumber() - 1];
 
                         if (info.UseCount == 0 && !info.PreAllocated)
                         {
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
index cd36bdc028..88adeeb0f3 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
@@ -976,7 +976,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
         {
             if (operand.Kind == OperandKind.LocalVariable)
             {
-                return operand.AsInt32();
+                return operand.GetLocalNumber();
             }
             else if (operand.Kind == OperandKind.Register)
             {
diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs
index 7b486c55d5..ec02393921 100644
--- a/ARMeilleure/IntermediateRepresentation/Operand.cs
+++ b/ARMeilleure/IntermediateRepresentation/Operand.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
 namespace ARMeilleure.IntermediateRepresentation
@@ -91,6 +92,13 @@ namespace ARMeilleure.IntermediateRepresentation
             return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24));
         }
 
+        public int GetLocalNumber()
+        {
+            Debug.Assert(Kind == OperandKind.LocalVariable);
+
+            return (int)Value;
+        }
+
         public byte AsByte()
         {
             return (byte)Value;
diff --git a/ARMeilleure/Translation/ControlFlowGraph.cs b/ARMeilleure/Translation/ControlFlowGraph.cs
index ee1a245e08..4c76d5dd18 100644
--- a/ARMeilleure/Translation/ControlFlowGraph.cs
+++ b/ARMeilleure/Translation/ControlFlowGraph.cs
@@ -10,15 +10,17 @@ namespace ARMeilleure.Translation
         private BasicBlock[] _postOrderBlocks;
         private int[] _postOrderMap;
 
+        public int LocalsCount { get; }
         public BasicBlock Entry { get; }
         public IntrusiveList<BasicBlock> Blocks { get; }
         public BasicBlock[] PostOrderBlocks => _postOrderBlocks;
         public int[] PostOrderMap => _postOrderMap; 
 
-        public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks)
+        public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks, int localsCount)
         {
             Entry = entry;
             Blocks = blocks;
+            LocalsCount = localsCount;
 
             Update(removeUnreachableBlocks: true);
         }
diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs
index 5c608b3d36..cc2205cecb 100644
--- a/ARMeilleure/Translation/EmitterContext.cs
+++ b/ARMeilleure/Translation/EmitterContext.cs
@@ -12,6 +12,8 @@ namespace ARMeilleure.Translation
 {
     class EmitterContext
     {
+        private int _localsCount;
+
         private readonly Dictionary<Operand, BasicBlock> _irLabels;
         private readonly IntrusiveList<BasicBlock> _irBlocks;
 
@@ -23,6 +25,8 @@ namespace ARMeilleure.Translation
 
         public EmitterContext()
         {
+            _localsCount = 0;
+
             _irLabels = new Dictionary<Operand, BasicBlock>();
             _irBlocks = new IntrusiveList<BasicBlock>();
 
@@ -30,6 +34,15 @@ namespace ARMeilleure.Translation
             _nextBlockFreq = BasicBlockFrequency.Default;
         }
 
+        public Operand AllocateLocal(OperandType type)
+        {
+            Operand local = Local(type);
+
+            local.NumberLocal(++_localsCount);
+
+            return local;
+        }
+
         public Operand Add(Operand op1, Operand op2)
         {
             return Add(Instruction.Add, Local(op1.Type), op1, op2);
@@ -223,9 +236,10 @@ namespace ARMeilleure.Translation
 
         public Operand Copy(Operand dest, Operand op1)
         {
-            if (dest.Kind != OperandKind.Register)
+            if (dest.Kind != OperandKind.Register &&
+                (dest.Kind != OperandKind.LocalVariable || dest.GetLocalNumber() == 0))
             {
-                throw new ArgumentException($"Invalid dest operand kind \"{dest.Kind}\".");
+                throw new ArgumentException($"Destination operand must be a Register or a numbered LocalVariable.");
             }
 
             return Add(Instruction.Copy, dest, op1);
@@ -670,7 +684,7 @@ namespace ARMeilleure.Translation
 
         public ControlFlowGraph GetControlFlowGraph()
         {
-            return new ControlFlowGraph(_irBlocks.First, _irBlocks);
+            return new ControlFlowGraph(_irBlocks.First, _irBlocks, _localsCount);
         }
     }
 }
diff --git a/ARMeilleure/Translation/SsaConstruction.cs b/ARMeilleure/Translation/SsaConstruction.cs
index 1c6e83c9ce..76cb9a4424 100644
--- a/ARMeilleure/Translation/SsaConstruction.cs
+++ b/ARMeilleure/Translation/SsaConstruction.cs
@@ -45,7 +45,7 @@ namespace ARMeilleure.Translation
         public static void Construct(ControlFlowGraph cfg)
         {
             var globalDefs = new DefMap[cfg.Blocks.Count];
-            var localDefs = new Operand[RegisterConsts.TotalCount];
+            var localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount];
 
             var dfPhiBlocks = new Queue<BasicBlock>();
 
@@ -264,6 +264,12 @@ namespace ARMeilleure.Translation
 
                 return true;
             }
+            else if (operand is { Kind: OperandKind.LocalVariable } && operand.GetLocalNumber() > 0)
+            {
+                result = RegisterConsts.TotalCount + operand.GetLocalNumber() - 1;
+
+                return true;
+            }
 
             result = -1;
 
@@ -274,7 +280,7 @@ namespace ARMeilleure.Translation
         {
             if (!TryGetId(operand, out int key))
             {
-                Debug.Fail("OperandKind must be Register.");
+                Debug.Fail("OperandKind must be Register or a numbered LocalVariable.");
             }
 
             return key;