1*0b57cec5SDimitry Andric //===- DemoteRegToStack.cpp - Move a virtual register to the stack --------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
10*0b57cec5SDimitry Andric #include "llvm/Analysis/CFG.h"
11*0b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
12*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
13*0b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
14*0b57cec5SDimitry Andric #include "llvm/IR/Type.h"
15*0b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
16*0b57cec5SDimitry Andric using namespace llvm;
17*0b57cec5SDimitry Andric 
18*0b57cec5SDimitry Andric /// DemoteRegToStack - This function takes a virtual register computed by an
19*0b57cec5SDimitry Andric /// Instruction and replaces it with a slot in the stack frame, allocated via
20*0b57cec5SDimitry Andric /// alloca.  This allows the CFG to be changed around without fear of
21*0b57cec5SDimitry Andric /// invalidating the SSA information for the value.  It returns the pointer to
22*0b57cec5SDimitry Andric /// the alloca inserted to create a stack slot for I.
DemoteRegToStack(Instruction & I,bool VolatileLoads,Instruction * AllocaPoint)23*0b57cec5SDimitry Andric AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,
24*0b57cec5SDimitry Andric                                    Instruction *AllocaPoint) {
25*0b57cec5SDimitry Andric   if (I.use_empty()) {
26*0b57cec5SDimitry Andric     I.eraseFromParent();
27*0b57cec5SDimitry Andric     return nullptr;
28*0b57cec5SDimitry Andric   }
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric   Function *F = I.getParent()->getParent();
31*0b57cec5SDimitry Andric   const DataLayout &DL = F->getParent()->getDataLayout();
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric   // Create a stack slot to hold the value.
34*0b57cec5SDimitry Andric   AllocaInst *Slot;
35*0b57cec5SDimitry Andric   if (AllocaPoint) {
36*0b57cec5SDimitry Andric     Slot = new AllocaInst(I.getType(), DL.getAllocaAddrSpace(), nullptr,
37*0b57cec5SDimitry Andric                           I.getName()+".reg2mem", AllocaPoint);
38*0b57cec5SDimitry Andric   } else {
39*0b57cec5SDimitry Andric     Slot = new AllocaInst(I.getType(), DL.getAllocaAddrSpace(), nullptr,
40*0b57cec5SDimitry Andric                           I.getName() + ".reg2mem", &F->getEntryBlock().front());
41*0b57cec5SDimitry Andric   }
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric   // We cannot demote invoke instructions to the stack if their normal edge
44*0b57cec5SDimitry Andric   // is critical. Therefore, split the critical edge and create a basic block
45*0b57cec5SDimitry Andric   // into which the store can be inserted.
46*0b57cec5SDimitry Andric   if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
47*0b57cec5SDimitry Andric     if (!II->getNormalDest()->getSinglePredecessor()) {
48*0b57cec5SDimitry Andric       unsigned SuccNum = GetSuccessorNumber(II->getParent(), II->getNormalDest());
49*0b57cec5SDimitry Andric       assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!");
50*0b57cec5SDimitry Andric       BasicBlock *BB = SplitCriticalEdge(II, SuccNum);
51*0b57cec5SDimitry Andric       assert(BB && "Unable to split critical edge.");
52*0b57cec5SDimitry Andric       (void)BB;
53*0b57cec5SDimitry Andric     }
54*0b57cec5SDimitry Andric   }
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric   // Change all of the users of the instruction to read from the stack slot.
57*0b57cec5SDimitry Andric   while (!I.use_empty()) {
58*0b57cec5SDimitry Andric     Instruction *U = cast<Instruction>(I.user_back());
59*0b57cec5SDimitry Andric     if (PHINode *PN = dyn_cast<PHINode>(U)) {
60*0b57cec5SDimitry Andric       // If this is a PHI node, we can't insert a load of the value before the
61*0b57cec5SDimitry Andric       // use.  Instead insert the load in the predecessor block corresponding
62*0b57cec5SDimitry Andric       // to the incoming value.
63*0b57cec5SDimitry Andric       //
64*0b57cec5SDimitry Andric       // Note that if there are multiple edges from a basic block to this PHI
65*0b57cec5SDimitry Andric       // node that we cannot have multiple loads. The problem is that the
66*0b57cec5SDimitry Andric       // resulting PHI node will have multiple values (from each load) coming in
67*0b57cec5SDimitry Andric       // from the same block, which is illegal SSA form. For this reason, we
68*0b57cec5SDimitry Andric       // keep track of and reuse loads we insert.
69*0b57cec5SDimitry Andric       DenseMap<BasicBlock*, Value*> Loads;
70*0b57cec5SDimitry Andric       for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
71*0b57cec5SDimitry Andric         if (PN->getIncomingValue(i) == &I) {
72*0b57cec5SDimitry Andric           Value *&V = Loads[PN->getIncomingBlock(i)];
73*0b57cec5SDimitry Andric           if (!V) {
74*0b57cec5SDimitry Andric             // Insert the load into the predecessor block
75*0b57cec5SDimitry Andric             V = new LoadInst(I.getType(), Slot, I.getName() + ".reload",
76*0b57cec5SDimitry Andric                              VolatileLoads,
77*0b57cec5SDimitry Andric                              PN->getIncomingBlock(i)->getTerminator());
78*0b57cec5SDimitry Andric           }
79*0b57cec5SDimitry Andric           PN->setIncomingValue(i, V);
80*0b57cec5SDimitry Andric         }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric     } else {
83*0b57cec5SDimitry Andric       // If this is a normal instruction, just insert a load.
84*0b57cec5SDimitry Andric       Value *V = new LoadInst(I.getType(), Slot, I.getName() + ".reload",
85*0b57cec5SDimitry Andric                               VolatileLoads, U);
86*0b57cec5SDimitry Andric       U->replaceUsesOfWith(&I, V);
87*0b57cec5SDimitry Andric     }
88*0b57cec5SDimitry Andric   }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric   // Insert stores of the computed value into the stack slot. We have to be
91*0b57cec5SDimitry Andric   // careful if I is an invoke instruction, because we can't insert the store
92*0b57cec5SDimitry Andric   // AFTER the terminator instruction.
93*0b57cec5SDimitry Andric   BasicBlock::iterator InsertPt;
94*0b57cec5SDimitry Andric   if (!I.isTerminator()) {
95*0b57cec5SDimitry Andric     InsertPt = ++I.getIterator();
96*0b57cec5SDimitry Andric     for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
97*0b57cec5SDimitry Andric       /* empty */;   // Don't insert before PHI nodes or landingpad instrs.
98*0b57cec5SDimitry Andric   } else {
99*0b57cec5SDimitry Andric     InvokeInst &II = cast<InvokeInst>(I);
100*0b57cec5SDimitry Andric     InsertPt = II.getNormalDest()->getFirstInsertionPt();
101*0b57cec5SDimitry Andric   }
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric   new StoreInst(&I, Slot, &*InsertPt);
104*0b57cec5SDimitry Andric   return Slot;
105*0b57cec5SDimitry Andric }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric /// DemotePHIToStack - This function takes a virtual register computed by a PHI
108*0b57cec5SDimitry Andric /// node and replaces it with a slot in the stack frame allocated via alloca.
109*0b57cec5SDimitry Andric /// The PHI node is deleted. It returns the pointer to the alloca inserted.
DemotePHIToStack(PHINode * P,Instruction * AllocaPoint)110*0b57cec5SDimitry Andric AllocaInst *llvm::DemotePHIToStack(PHINode *P, Instruction *AllocaPoint) {
111*0b57cec5SDimitry Andric   if (P->use_empty()) {
112*0b57cec5SDimitry Andric     P->eraseFromParent();
113*0b57cec5SDimitry Andric     return nullptr;
114*0b57cec5SDimitry Andric   }
115*0b57cec5SDimitry Andric 
116*0b57cec5SDimitry Andric   const DataLayout &DL = P->getModule()->getDataLayout();
117*0b57cec5SDimitry Andric 
118*0b57cec5SDimitry Andric   // Create a stack slot to hold the value.
119*0b57cec5SDimitry Andric   AllocaInst *Slot;
120*0b57cec5SDimitry Andric   if (AllocaPoint) {
121*0b57cec5SDimitry Andric     Slot = new AllocaInst(P->getType(), DL.getAllocaAddrSpace(), nullptr,
122*0b57cec5SDimitry Andric                           P->getName()+".reg2mem", AllocaPoint);
123*0b57cec5SDimitry Andric   } else {
124*0b57cec5SDimitry Andric     Function *F = P->getParent()->getParent();
125*0b57cec5SDimitry Andric     Slot = new AllocaInst(P->getType(), DL.getAllocaAddrSpace(), nullptr,
126*0b57cec5SDimitry Andric                           P->getName() + ".reg2mem",
127*0b57cec5SDimitry Andric                           &F->getEntryBlock().front());
128*0b57cec5SDimitry Andric   }
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric   // Iterate over each operand inserting a store in each predecessor.
131*0b57cec5SDimitry Andric   for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) {
132*0b57cec5SDimitry Andric     if (InvokeInst *II = dyn_cast<InvokeInst>(P->getIncomingValue(i))) {
133*0b57cec5SDimitry Andric       assert(II->getParent() != P->getIncomingBlock(i) &&
134*0b57cec5SDimitry Andric              "Invoke edge not supported yet"); (void)II;
135*0b57cec5SDimitry Andric     }
136*0b57cec5SDimitry Andric     new StoreInst(P->getIncomingValue(i), Slot,
137*0b57cec5SDimitry Andric                   P->getIncomingBlock(i)->getTerminator());
138*0b57cec5SDimitry Andric   }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric   // Insert a load in place of the PHI and replace all uses.
141*0b57cec5SDimitry Andric   BasicBlock::iterator InsertPt = P->getIterator();
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric   for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
144*0b57cec5SDimitry Andric     /* empty */;   // Don't insert before PHI nodes or landingpad instrs.
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric   Value *V =
147*0b57cec5SDimitry Andric       new LoadInst(P->getType(), Slot, P->getName() + ".reload", &*InsertPt);
148*0b57cec5SDimitry Andric   P->replaceAllUsesWith(V);
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric   // Delete PHI.
151*0b57cec5SDimitry Andric   P->eraseFromParent();
152*0b57cec5SDimitry Andric   return Slot;
153*0b57cec5SDimitry Andric }
154