0716ca92a3c33f360f0cf4edc01e9b55b2ca3c77
[oota-llvm.git] / lib / CodeGen / TwoAddressInstructionPass.cpp
1 //===-- TwoAddressInstructionPass.cpp - Two-Address instruction pass ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the LiveInterval analysis pass which is used
11 // by the Linear Scan Register allocator. This pass linearizes the
12 // basic blocks of the function in DFS order and uses the
13 // LiveVariables pass to conservatively compute live intervals for
14 // each virtual and physical register.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #define DEBUG_TYPE "twoaddrinstr"
19 #include "llvm/CodeGen/TwoAddressInstructionPass.h"
20 #include "llvm/Function.h"
21 #include "llvm/CodeGen/LiveVariables.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/Passes.h"
26 #include "llvm/CodeGen/SSARegMap.h"
27 #include "llvm/Target/MRegisterInfo.h"
28 #include "llvm/Target/TargetInstrInfo.h"
29 #include "llvm/Target/TargetMachine.h"
30 #include "llvm/Target/TargetRegInfo.h"
31 #include "Support/Debug.h"
32 #include "Support/Statistic.h"
33 #include "Support/STLExtras.h"
34 #include <iostream>
35
36 using namespace llvm;
37
38 namespace {
39     RegisterAnalysis<TwoAddressInstructionPass> X(
40         "twoaddressinstruction", "Two-Address instruction pass");
41
42     Statistic<> numTwoAddressInstrs("twoaddressinstruction",
43                                     "Number of two-address instructions");
44     Statistic<> numInstrsAdded("twoaddressinstruction",
45                                "Number of instructions added");
46 };
47
48 void TwoAddressInstructionPass::getAnalysisUsage(AnalysisUsage &AU) const
49 {
50     AU.addPreserved<LiveVariables>();
51     AU.addRequired<LiveVariables>();
52     AU.addPreservedID(PHIEliminationID);
53     AU.addRequiredID(PHIEliminationID);
54     MachineFunctionPass::getAnalysisUsage(AU);
55 }
56
57 /// runOnMachineFunction - Reduce two-address instructions to two
58 /// operands
59 ///
60 bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &fn) {
61     DEBUG(std::cerr << "Machine Function\n");
62     mf_ = &fn;
63     tm_ = &fn.getTarget();
64     mri_ = tm_->getRegisterInfo();
65     lv_ = &getAnalysis<LiveVariables>();
66
67     const TargetInstrInfo& tii = tm_->getInstrInfo();
68
69     for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
70          mbbi != mbbe; ++mbbi) {
71         for (MachineBasicBlock::iterator mii = mbbi->begin();
72              mii != mbbi->end(); ++mii) {
73             MachineInstr* mi = *mii;
74
75             unsigned opcode = mi->getOpcode();
76             // ignore if it is not a two-address instruction
77             if (!tii.isTwoAddrInstr(opcode))
78                 continue;
79
80             ++numTwoAddressInstrs;
81
82             DEBUG(std::cerr << "\tinstruction: "; mi->print(std::cerr, *tm_));
83
84             // we have nothing to do if the two operands are the same
85             if (mi->getOperand(0).getAllocatedRegNum() ==
86                 mi->getOperand(1).getAllocatedRegNum())
87                 continue;
88
89             assert(mi->getOperand(1).isRegister() &&
90                    mi->getOperand(1).getAllocatedRegNum() &&
91                    mi->getOperand(1).isUse() &&
92                    "two address instruction invalid");
93
94             // rewrite:
95             //     a = b op c
96             // to:
97             //     a = b
98             //     a = a op c
99             unsigned regA = mi->getOperand(0).getAllocatedRegNum();
100             unsigned regB = mi->getOperand(1).getAllocatedRegNum();
101             bool regAisPhysical = regA < MRegisterInfo::FirstVirtualRegister;
102             bool regBisPhysical = regB < MRegisterInfo::FirstVirtualRegister;
103
104             const TargetRegisterClass* rc = regAisPhysical ?
105                 mri_->getRegClass(regA) :
106                 mf_->getSSARegMap()->getRegClass(regA);
107
108             numInstrsAdded += mri_->copyRegToReg(*mbbi, mii, regA, regB, rc);
109
110             MachineInstr* prevMi = *(mii - 1);
111             DEBUG(std::cerr << "\t\tadded instruction: ";
112                   prevMi->print(std::cerr, *tm_));
113
114             // update live variables for regA
115             if (regAisPhysical) {
116                 lv_->HandlePhysRegDef(regA, prevMi);
117             }
118             else {
119                 LiveVariables::VarInfo& varInfo = lv_->getVarInfo(regA);
120                 varInfo.DefInst = prevMi;
121             }
122
123             // update live variables for regB
124             if (regBisPhysical) {
125                 lv_->HandlePhysRegUse(regB, prevMi);
126             }
127             else {
128                 if (lv_->removeVirtualRegisterKilled(regB, &*mbbi, mi))
129                     lv_->addVirtualRegisterKilled(regB, &*mbbi, prevMi);
130
131                 if (lv_->removeVirtualRegisterDead(regB, &*mbbi, mi))
132                     lv_->addVirtualRegisterDead(regB, &*mbbi, prevMi);
133             }
134
135             // replace all occurences of regB with regA
136             for (unsigned i = 1; i < mi->getNumOperands(); ++i) {
137                 if (mi->getOperand(i).isRegister() &&
138                     mi->getOperand(i).getReg() == regB)
139                     mi->SetMachineOperandReg(i, regA);
140             }
141             DEBUG(std::cerr << "\t\tmodified original to: ";
142                   mi->print(std::cerr, *tm_));
143             assert(mi->getOperand(0).getAllocatedRegNum() ==
144                    mi->getOperand(1).getAllocatedRegNum());
145         }
146     }
147
148     return numInstrsAdded != 0;
149 }