/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // Subclass of MipsDAGToDAGISel specialized for mips16. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "Mips16ISelDAGToDAG.h" |
15 | | #include "MCTargetDesc/MipsBaseInfo.h" |
16 | | #include "Mips.h" |
17 | | #include "MipsMachineFunction.h" |
18 | | #include "MipsRegisterInfo.h" |
19 | | #include "llvm/CodeGen/MachineConstantPool.h" |
20 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
21 | | #include "llvm/CodeGen/MachineFunction.h" |
22 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
23 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
24 | | #include "llvm/CodeGen/SelectionDAGNodes.h" |
25 | | #include "llvm/IR/CFG.h" |
26 | | #include "llvm/IR/GlobalValue.h" |
27 | | #include "llvm/IR/Instructions.h" |
28 | | #include "llvm/IR/Intrinsics.h" |
29 | | #include "llvm/IR/Type.h" |
30 | | #include "llvm/Support/Debug.h" |
31 | | #include "llvm/Support/ErrorHandling.h" |
32 | | #include "llvm/Support/raw_ostream.h" |
33 | | #include "llvm/Target/TargetMachine.h" |
34 | | using namespace llvm; |
35 | | |
36 | | #define DEBUG_TYPE "mips-isel" |
37 | | |
38 | 12.3k | bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { |
39 | 12.3k | Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); |
40 | 12.3k | if (!Subtarget->inMips16Mode()) |
41 | 11.9k | return false; |
42 | 377 | return MipsDAGToDAGISel::runOnMachineFunction(MF); |
43 | 377 | } |
44 | | /// Select multiply instructions. |
45 | | std::pair<SDNode *, SDNode *> |
46 | | Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty, |
47 | 8 | bool HasLo, bool HasHi) { |
48 | 8 | SDNode *Lo = nullptr, *Hi = nullptr; |
49 | 8 | SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0), |
50 | 8 | N->getOperand(1)); |
51 | 8 | SDValue InFlag = SDValue(Mul, 0); |
52 | 8 | |
53 | 8 | if (HasLo8 ) { |
54 | 8 | unsigned Opcode = Mips::Mflo16; |
55 | 8 | Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag); |
56 | 8 | InFlag = SDValue(Lo, 1); |
57 | 8 | } |
58 | 8 | if (HasHi8 ) { |
59 | 8 | unsigned Opcode = Mips::Mfhi16; |
60 | 8 | Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag); |
61 | 8 | } |
62 | 8 | return std::make_pair(Lo, Hi); |
63 | 8 | } |
64 | | |
65 | 377 | void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { |
66 | 377 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
67 | 377 | |
68 | 377 | if (!MipsFI->globalBaseRegSet()) |
69 | 180 | return; |
70 | 197 | |
71 | 197 | MachineBasicBlock &MBB = MF.front(); |
72 | 197 | MachineBasicBlock::iterator I = MBB.begin(); |
73 | 197 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
74 | 197 | const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); |
75 | 197 | DebugLoc DL; |
76 | 197 | unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); |
77 | 197 | const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; |
78 | 197 | |
79 | 197 | V0 = RegInfo.createVirtualRegister(RC); |
80 | 197 | V1 = RegInfo.createVirtualRegister(RC); |
81 | 197 | V2 = RegInfo.createVirtualRegister(RC); |
82 | 197 | |
83 | 197 | |
84 | 197 | BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0) |
85 | 197 | .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); |
86 | 197 | BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1) |
87 | 197 | .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); |
88 | 197 | |
89 | 197 | BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16); |
90 | 197 | BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) |
91 | 197 | .addReg(V1) |
92 | 197 | .addReg(V2); |
93 | 197 | } |
94 | | |
95 | 377 | void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { |
96 | 377 | initGlobalBaseReg(MF); |
97 | 377 | } |
98 | | |
99 | | bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, |
100 | 3.65k | SDValue &Offset) { |
101 | 3.65k | SDLoc DL(Addr); |
102 | 3.65k | EVT ValTy = Addr.getValueType(); |
103 | 3.65k | |
104 | 3.65k | // if Address is FI, get the TargetFrameIndex. |
105 | 3.65k | if (SPAllowed3.65k ) { |
106 | 3.62k | if (FrameIndexSDNode *FIN3.62k = dyn_cast<FrameIndexSDNode>(Addr)) { |
107 | 104 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); |
108 | 104 | Offset = CurDAG->getTargetConstant(0, DL, ValTy); |
109 | 104 | return true; |
110 | 104 | } |
111 | 3.55k | } |
112 | 3.55k | // on PIC code Load GA |
113 | 3.55k | if (3.55k Addr.getOpcode() == MipsISD::Wrapper3.55k ) { |
114 | 1.36k | Base = Addr.getOperand(0); |
115 | 1.36k | Offset = Addr.getOperand(1); |
116 | 1.36k | return true; |
117 | 1.36k | } |
118 | 2.19k | if (2.19k !TM.isPositionIndependent()2.19k ) { |
119 | 1.26k | if ((Addr.getOpcode() == ISD::TargetExternalSymbol || |
120 | 1.26k | Addr.getOpcode() == ISD::TargetGlobalAddress)) |
121 | 0 | return false; |
122 | 2.19k | } |
123 | 2.19k | // Addresses of the form FI+const or FI|const |
124 | 2.19k | if (2.19k CurDAG->isBaseWithConstantOffset(Addr)2.19k ) { |
125 | 731 | ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); |
126 | 731 | if (isInt<16>(CN->getSExtValue())731 ) { |
127 | 731 | // If the first operand is a FI, get the TargetFI Node |
128 | 731 | if (SPAllowed731 ) { |
129 | 727 | if (FrameIndexSDNode *FIN = |
130 | 42 | dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { |
131 | 42 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); |
132 | 42 | Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); |
133 | 42 | return true; |
134 | 42 | } |
135 | 689 | } |
136 | 689 | |
137 | 689 | Base = Addr.getOperand(0); |
138 | 689 | Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); |
139 | 689 | return true; |
140 | 689 | } |
141 | 731 | } |
142 | 1.46k | // Operand is a result from an ADD. |
143 | 1.46k | if (1.46k Addr.getOpcode() == ISD::ADD1.46k ) { |
144 | 713 | // When loading from constant pools, load the lower address part in |
145 | 713 | // the instruction itself. Example, instead of: |
146 | 713 | // lui $2, %hi($CPI1_0) |
147 | 713 | // addiu $2, $2, %lo($CPI1_0) |
148 | 713 | // lwc1 $f0, 0($2) |
149 | 713 | // Generate: |
150 | 713 | // lui $2, %hi($CPI1_0) |
151 | 713 | // lwc1 $f0, %lo($CPI1_0)($2) |
152 | 713 | if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || |
153 | 713 | Addr.getOperand(1).getOpcode() == MipsISD::GPRel5 ) { |
154 | 708 | SDValue Opnd0 = Addr.getOperand(1).getOperand(0); |
155 | 708 | if (isa<ConstantPoolSDNode>(Opnd0) || 708 isa<GlobalAddressSDNode>(Opnd0)708 || |
156 | 708 | isa<JumpTableSDNode>(Opnd0)1 ) { |
157 | 708 | Base = Addr.getOperand(0); |
158 | 708 | Offset = Opnd0; |
159 | 708 | return true; |
160 | 708 | } |
161 | 753 | } |
162 | 713 | } |
163 | 753 | Base = Addr; |
164 | 753 | Offset = CurDAG->getTargetConstant(0, DL, ValTy); |
165 | 753 | return true; |
166 | 753 | } |
167 | | |
168 | | bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, |
169 | 38 | SDValue &Offset) { |
170 | 38 | return selectAddr(false, Addr, Base, Offset); |
171 | 38 | } |
172 | | |
173 | | bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, |
174 | 3.62k | SDValue &Offset) { |
175 | 3.62k | return selectAddr(true, Addr, Base, Offset); |
176 | 3.62k | } |
177 | | |
178 | | /// Select instructions not customized! Used for |
179 | | /// expanded, promoted and normal instructions |
180 | 19.7k | bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { |
181 | 19.7k | unsigned Opcode = Node->getOpcode(); |
182 | 19.7k | SDLoc DL(Node); |
183 | 19.7k | |
184 | 19.7k | /// |
185 | 19.7k | // Instruction Selection not handled by the auto-generated |
186 | 19.7k | // tablegen selection should be handled here. |
187 | 19.7k | /// |
188 | 19.7k | EVT NodeTy = Node->getValueType(0); |
189 | 19.7k | unsigned MultOpc; |
190 | 19.7k | |
191 | 19.7k | switch (Opcode) { |
192 | 19.7k | default: |
193 | 19.7k | break; |
194 | 19.7k | |
195 | 0 | case ISD::SUBE: |
196 | 0 | case ISD::ADDE: { |
197 | 0 | SDValue InFlag = Node->getOperand(2), CmpLHS; |
198 | 0 | unsigned Opc = InFlag.getOpcode(); |
199 | 0 | (void)Opc; |
200 | 0 | assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || |
201 | 0 | (Opc == ISD::SUBC || Opc == ISD::SUBE)) && |
202 | 0 | "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); |
203 | 0 |
|
204 | 0 | unsigned MOp; |
205 | 0 | if (Opcode == ISD::ADDE0 ) { |
206 | 0 | CmpLHS = InFlag.getValue(0); |
207 | 0 | MOp = Mips::AdduRxRyRz16; |
208 | 0 | } else { |
209 | 0 | CmpLHS = InFlag.getOperand(0); |
210 | 0 | MOp = Mips::SubuRxRyRz16; |
211 | 0 | } |
212 | 0 |
|
213 | 0 | SDValue Ops[] = {CmpLHS, InFlag.getOperand(1)}; |
214 | 0 |
|
215 | 0 | SDValue LHS = Node->getOperand(0); |
216 | 0 | SDValue RHS = Node->getOperand(1); |
217 | 0 |
|
218 | 0 | EVT VT = LHS.getValueType(); |
219 | 0 |
|
220 | 0 | unsigned Sltu_op = Mips::SltuRxRyRz16; |
221 | 0 | SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops); |
222 | 0 | unsigned Addu_op = Mips::AdduRxRyRz16; |
223 | 0 | SDNode *AddCarry = |
224 | 0 | CurDAG->getMachineNode(Addu_op, DL, VT, SDValue(Carry, 0), RHS); |
225 | 0 |
|
226 | 0 | CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0)); |
227 | 0 | return true; |
228 | 0 | } |
229 | 0 |
|
230 | 0 | /// Mul with two results |
231 | 8 | case ISD::SMUL_LOHI: |
232 | 8 | case ISD::UMUL_LOHI: { |
233 | 8 | MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy164 : Mips::MultRxRy164 ); |
234 | 8 | std::pair<SDNode *, SDNode *> LoHi = |
235 | 8 | selectMULT(Node, MultOpc, DL, NodeTy, true, true); |
236 | 8 | if (!SDValue(Node, 0).use_empty()) |
237 | 8 | ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); |
238 | 8 | |
239 | 8 | if (!SDValue(Node, 1).use_empty()) |
240 | 8 | ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); |
241 | 8 | |
242 | 8 | CurDAG->RemoveDeadNode(Node); |
243 | 8 | return true; |
244 | 8 | } |
245 | 8 | |
246 | 0 | case ISD::MULHS: |
247 | 0 | case ISD::MULHU: { |
248 | 0 | MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy160 : Mips::MultRxRy160 ); |
249 | 0 | auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true); |
250 | 0 | ReplaceNode(Node, LoHi.second); |
251 | 0 | return true; |
252 | 19.7k | } |
253 | 19.7k | } |
254 | 19.7k | |
255 | 19.7k | return false; |
256 | 19.7k | } |
257 | | |
258 | | FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM, |
259 | 1.72k | CodeGenOpt::Level OptLevel) { |
260 | 1.72k | return new Mips16DAGToDAGISel(TM, OptLevel); |
261 | 1.72k | } |