[SPARC] Revamp AnalyzeBranch and add ReverseBranchCondition.
[oota-llvm.git] / lib / Target / Sparc / SparcISelDAGToDAG.cpp
1 //===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===//
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 // This file defines an instruction selector for the SPARC target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SparcTargetMachine.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/SelectionDAGISel.h"
17 #include "llvm/IR/Intrinsics.h"
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace llvm;
23
24 //===----------------------------------------------------------------------===//
25 // Instruction Selector Implementation
26 //===----------------------------------------------------------------------===//
27
28 //===--------------------------------------------------------------------===//
29 /// SparcDAGToDAGISel - SPARC specific code to select SPARC machine
30 /// instructions for SelectionDAG operations.
31 ///
32 namespace {
33 class SparcDAGToDAGISel : public SelectionDAGISel {
34   /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can
35   /// make the right decision when generating code for different targets.
36   const SparcSubtarget *Subtarget;
37 public:
38   explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(tm) {}
39
40   bool runOnMachineFunction(MachineFunction &MF) override {
41     Subtarget = &MF.getSubtarget<SparcSubtarget>();
42     return SelectionDAGISel::runOnMachineFunction(MF);
43   }
44
45   SDNode *Select(SDNode *N) override;
46
47   // Complex Pattern Selectors.
48   bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
49   bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
50
51   /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
52   /// inline asm expressions.
53   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
54                                     unsigned ConstraintID,
55                                     std::vector<SDValue> &OutOps) override;
56
57   const char *getPassName() const override {
58     return "SPARC DAG->DAG Pattern Instruction Selection";
59   }
60
61   // Include the pieces autogenerated from the target description.
62 #include "SparcGenDAGISel.inc"
63
64 private:
65   SDNode* getGlobalBaseReg();
66   SDNode *SelectInlineAsm(SDNode *N);
67 };
68 }  // end anonymous namespace
69
70 SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
71   unsigned GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
72   return CurDAG->getRegister(GlobalBaseReg,
73                              TLI->getPointerTy(CurDAG->getDataLayout()))
74       .getNode();
75 }
76
77 bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
78                                      SDValue &Base, SDValue &Offset) {
79   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
80     Base = CurDAG->getTargetFrameIndex(
81         FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
82     Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
83     return true;
84   }
85   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
86       Addr.getOpcode() == ISD::TargetGlobalAddress ||
87       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
88     return false;  // direct calls.
89
90   if (Addr.getOpcode() == ISD::ADD) {
91     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
92       if (isInt<13>(CN->getSExtValue())) {
93         if (FrameIndexSDNode *FIN =
94                 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
95           // Constant offset from frame ref.
96           Base = CurDAG->getTargetFrameIndex(
97               FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
98         } else {
99           Base = Addr.getOperand(0);
100         }
101         Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr),
102                                            MVT::i32);
103         return true;
104       }
105     }
106     if (Addr.getOperand(0).getOpcode() == SPISD::Lo) {
107       Base = Addr.getOperand(1);
108       Offset = Addr.getOperand(0).getOperand(0);
109       return true;
110     }
111     if (Addr.getOperand(1).getOpcode() == SPISD::Lo) {
112       Base = Addr.getOperand(0);
113       Offset = Addr.getOperand(1).getOperand(0);
114       return true;
115     }
116   }
117   Base = Addr;
118   Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
119   return true;
120 }
121
122 bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
123   if (Addr.getOpcode() == ISD::FrameIndex) return false;
124   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
125       Addr.getOpcode() == ISD::TargetGlobalAddress ||
126       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
127     return false;  // direct calls.
128
129   if (Addr.getOpcode() == ISD::ADD) {
130     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
131       if (isInt<13>(CN->getSExtValue()))
132         return false;  // Let the reg+imm pattern catch this!
133     if (Addr.getOperand(0).getOpcode() == SPISD::Lo ||
134         Addr.getOperand(1).getOpcode() == SPISD::Lo)
135       return false;  // Let the reg+imm pattern catch this!
136     R1 = Addr.getOperand(0);
137     R2 = Addr.getOperand(1);
138     return true;
139   }
140
141   R1 = Addr;
142   R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
143   return true;
144 }
145
146
147 // Re-assemble i64 arguments split up in SelectionDAGBuilder's
148 // visitInlineAsm / GetRegistersForValue functions.
149 //
150 // Note: This function was copied from, and is essentially identical
151 // to ARMISelDAGToDAG::SelectInlineAsm. It is very unfortunate that
152 // such hacking-up is necessary; a rethink of how inline asm operands
153 // are handled may be in order to make doing this more sane.
154 //
155 // TODO: fix inline asm support so I can simply tell it that 'i64'
156 // inputs to asm need to be allocated to the IntPair register type,
157 // and have that work. Then, delete this function.
158 SDNode *SparcDAGToDAGISel::SelectInlineAsm(SDNode *N){
159   std::vector<SDValue> AsmNodeOperands;
160   unsigned Flag, Kind;
161   bool Changed = false;
162   unsigned NumOps = N->getNumOperands();
163
164   // Normally, i64 data is bounded to two arbitrary GPRs for "%r"
165   // constraint.  However, some instructions (e.g. ldd/std) require
166   // (even/even+1) GPRs.
167
168   // So, here, we check for this case, and mutate the inlineasm to use
169   // a single IntPair register instead, which guarantees such even/odd
170   // placement.
171
172   SDLoc dl(N);
173   SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
174                                    : SDValue(nullptr,0);
175
176   SmallVector<bool, 8> OpChanged;
177   // Glue node will be appended late.
178   for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
179     SDValue op = N->getOperand(i);
180     AsmNodeOperands.push_back(op);
181
182     if (i < InlineAsm::Op_FirstOperand)
183       continue;
184
185     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
186       Flag = C->getZExtValue();
187       Kind = InlineAsm::getKind(Flag);
188     }
189     else
190       continue;
191
192     // Immediate operands to inline asm in the SelectionDAG are modeled with
193     // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
194     // the second is a constant with the value of the immediate. If we get here
195     // and we have a Kind_Imm, skip the next operand, and continue.
196     if (Kind == InlineAsm::Kind_Imm) {
197       SDValue op = N->getOperand(++i);
198       AsmNodeOperands.push_back(op);
199       continue;
200     }
201
202     unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
203     if (NumRegs)
204       OpChanged.push_back(false);
205
206     unsigned DefIdx = 0;
207     bool IsTiedToChangedOp = false;
208     // If it's a use that is tied with a previous def, it has no
209     // reg class constraint.
210     if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
211       IsTiedToChangedOp = OpChanged[DefIdx];
212
213     if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
214         && Kind != InlineAsm::Kind_RegDefEarlyClobber)
215       continue;
216
217     unsigned RC;
218     bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
219     if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID))
220         || NumRegs != 2)
221       continue;
222
223     assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
224     SDValue V0 = N->getOperand(i+1);
225     SDValue V1 = N->getOperand(i+2);
226     unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
227     unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
228     SDValue PairedReg;
229     MachineRegisterInfo &MRI = MF->getRegInfo();
230
231     if (Kind == InlineAsm::Kind_RegDef ||
232         Kind == InlineAsm::Kind_RegDefEarlyClobber) {
233       // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
234       // the original GPRs.
235
236       unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass);
237       PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
238       SDValue Chain = SDValue(N,0);
239
240       SDNode *GU = N->getGluedUser();
241       SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32,
242                                                Chain.getValue(1));
243
244       // Extract values from a GPRPair reg and copy to the original GPR reg.
245       SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32,
246                                                     RegCopy);
247       SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32,
248                                                     RegCopy);
249       SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
250                                         RegCopy.getValue(1));
251       SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
252
253       // Update the original glue user.
254       std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
255       Ops.push_back(T1.getValue(1));
256       CurDAG->UpdateNodeOperands(GU, Ops);
257     }
258     else {
259       // For Kind  == InlineAsm::Kind_RegUse, we first copy two GPRs into a
260       // GPRPair and then pass the GPRPair to the inline asm.
261       SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
262
263       // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
264       SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
265                                           Chain.getValue(1));
266       SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
267                                           T0.getValue(1));
268       SDValue Pair = SDValue(
269           CurDAG->getMachineNode(
270               TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32,
271               {
272                   CurDAG->getTargetConstant(SP::IntPairRegClassID, dl,
273                                             MVT::i32),
274                   T0,
275                   CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32),
276                   T1,
277                   CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32),
278               }),
279           0);
280
281       // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
282       // i32 VRs of inline asm with it.
283       unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass);
284       PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32);
285       Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
286
287       AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
288       Glue = Chain.getValue(1);
289     }
290
291     Changed = true;
292
293     if(PairedReg.getNode()) {
294       OpChanged[OpChanged.size() -1 ] = true;
295       Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
296       if (IsTiedToChangedOp)
297         Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
298       else
299         Flag = InlineAsm::getFlagWordForRegClass(Flag, SP::IntPairRegClassID);
300       // Replace the current flag.
301       AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
302           Flag, dl, MVT::i32);
303       // Add the new register node and skip the original two GPRs.
304       AsmNodeOperands.push_back(PairedReg);
305       // Skip the next two GPRs.
306       i += 2;
307     }
308   }
309
310   if (Glue.getNode())
311     AsmNodeOperands.push_back(Glue);
312   if (!Changed)
313     return nullptr;
314
315   SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
316       CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
317   New->setNodeId(-1);
318   return New.getNode();
319 }
320
321 SDNode *SparcDAGToDAGISel::Select(SDNode *N) {
322   SDLoc dl(N);
323   if (N->isMachineOpcode()) {
324     N->setNodeId(-1);
325     return nullptr;   // Already selected.
326   }
327
328   switch (N->getOpcode()) {
329   default: break;
330     case ISD::INLINEASM: {
331     SDNode *ResNode = SelectInlineAsm(N);
332     if (ResNode)
333       return ResNode;
334     break;
335   }
336   case SPISD::GLOBAL_BASE_REG:
337     return getGlobalBaseReg();
338
339   case ISD::SDIV:
340   case ISD::UDIV: {
341     // sdivx / udivx handle 64-bit divides.
342     if (N->getValueType(0) == MVT::i64)
343       break;
344     // FIXME: should use a custom expander to expose the SRA to the dag.
345     SDValue DivLHS = N->getOperand(0);
346     SDValue DivRHS = N->getOperand(1);
347
348     // Set the Y register to the high-part.
349     SDValue TopPart;
350     if (N->getOpcode() == ISD::SDIV) {
351       TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
352                                    CurDAG->getTargetConstant(31, dl, MVT::i32)),
353                         0);
354     } else {
355       TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
356     }
357     TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
358                                    SDValue())
359                   .getValue(1);
360
361     // FIXME: Handle div by immediate.
362     unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
363     return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS,
364                                 TopPart);
365   }
366   case ISD::MULHU:
367   case ISD::MULHS: {
368     // FIXME: Handle mul by immediate.
369     SDValue MulLHS = N->getOperand(0);
370     SDValue MulRHS = N->getOperand(1);
371     unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
372     SDNode *Mul =
373         CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MulLHS, MulRHS);
374     SDValue ResultHigh = SDValue(Mul, 1);
375     ReplaceUses(SDValue(N, 0), ResultHigh);
376     return nullptr;
377   }
378   }
379
380   return SelectCode(N);
381 }
382
383
384 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
385 /// inline asm expressions.
386 bool
387 SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
388                                                 unsigned ConstraintID,
389                                                 std::vector<SDValue> &OutOps) {
390   SDValue Op0, Op1;
391   switch (ConstraintID) {
392   default: return true;
393   case InlineAsm::Constraint_i:
394   case InlineAsm::Constraint_m: // memory
395    if (!SelectADDRrr(Op, Op0, Op1))
396      SelectADDRri(Op, Op0, Op1);
397    break;
398   }
399
400   OutOps.push_back(Op0);
401   OutOps.push_back(Op1);
402   return false;
403 }
404
405 /// createSparcISelDag - This pass converts a legalized DAG into a
406 /// SPARC-specific DAG, ready for instruction scheduling.
407 ///
408 FunctionPass *llvm::createSparcISelDag(SparcTargetMachine &TM) {
409   return new SparcDAGToDAGISel(TM);
410 }