LLVM  3.7.0
SparcISelDAGToDAG.cpp
Go to the documentation of this file.
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"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/Debug.h"
21 using namespace llvm;
22 
23 //===----------------------------------------------------------------------===//
24 // Instruction Selector Implementation
25 //===----------------------------------------------------------------------===//
26 
27 //===--------------------------------------------------------------------===//
28 /// SparcDAGToDAGISel - SPARC specific code to select SPARC machine
29 /// instructions for SelectionDAG operations.
30 ///
31 namespace {
32 class SparcDAGToDAGISel : public SelectionDAGISel {
33  /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can
34  /// make the right decision when generating code for different targets.
35  const SparcSubtarget *Subtarget;
36 public:
37  explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(tm) {}
38 
39  bool runOnMachineFunction(MachineFunction &MF) override {
40  Subtarget = &MF.getSubtarget<SparcSubtarget>();
42  }
43 
44  SDNode *Select(SDNode *N) override;
45 
46  // Complex Pattern Selectors.
47  bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
48  bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
49 
50  /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
51  /// inline asm expressions.
52  bool SelectInlineAsmMemoryOperand(const SDValue &Op,
53  unsigned ConstraintID,
54  std::vector<SDValue> &OutOps) override;
55 
56  const char *getPassName() const override {
57  return "SPARC DAG->DAG Pattern Instruction Selection";
58  }
59 
60  // Include the pieces autogenerated from the target description.
61 #include "SparcGenDAGISel.inc"
62 
63 private:
64  SDNode* getGlobalBaseReg();
65 };
66 } // end anonymous namespace
67 
68 SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
69  unsigned GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
70  return CurDAG->getRegister(GlobalBaseReg,
71  TLI->getPointerTy(CurDAG->getDataLayout()))
72  .getNode();
73 }
74 
75 bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
76  SDValue &Base, SDValue &Offset) {
77  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
78  Base = CurDAG->getTargetFrameIndex(
79  FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
80  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
81  return true;
82  }
83  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
86  return false; // direct calls.
87 
88  if (Addr.getOpcode() == ISD::ADD) {
89  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
90  if (isInt<13>(CN->getSExtValue())) {
91  if (FrameIndexSDNode *FIN =
92  dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
93  // Constant offset from frame ref.
94  Base = CurDAG->getTargetFrameIndex(
95  FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
96  } else {
97  Base = Addr.getOperand(0);
98  }
99  Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr),
100  MVT::i32);
101  return true;
102  }
103  }
104  if (Addr.getOperand(0).getOpcode() == SPISD::Lo) {
105  Base = Addr.getOperand(1);
106  Offset = Addr.getOperand(0).getOperand(0);
107  return true;
108  }
109  if (Addr.getOperand(1).getOpcode() == SPISD::Lo) {
110  Base = Addr.getOperand(0);
111  Offset = Addr.getOperand(1).getOperand(0);
112  return true;
113  }
114  }
115  Base = Addr;
116  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
117  return true;
118 }
119 
120 bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
121  if (Addr.getOpcode() == ISD::FrameIndex) return false;
122  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
125  return false; // direct calls.
126 
127  if (Addr.getOpcode() == ISD::ADD) {
128  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
129  if (isInt<13>(CN->getSExtValue()))
130  return false; // Let the reg+imm pattern catch this!
131  if (Addr.getOperand(0).getOpcode() == SPISD::Lo ||
132  Addr.getOperand(1).getOpcode() == SPISD::Lo)
133  return false; // Let the reg+imm pattern catch this!
134  R1 = Addr.getOperand(0);
135  R2 = Addr.getOperand(1);
136  return true;
137  }
138 
139  R1 = Addr;
140  R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
141  return true;
142 }
143 
145  SDLoc dl(N);
146  if (N->isMachineOpcode()) {
147  N->setNodeId(-1);
148  return nullptr; // Already selected.
149  }
150 
151  switch (N->getOpcode()) {
152  default: break;
154  return getGlobalBaseReg();
155 
156  case ISD::SDIV:
157  case ISD::UDIV: {
158  // sdivx / udivx handle 64-bit divides.
159  if (N->getValueType(0) == MVT::i64)
160  break;
161  // FIXME: should use a custom expander to expose the SRA to the dag.
162  SDValue DivLHS = N->getOperand(0);
163  SDValue DivRHS = N->getOperand(1);
164 
165  // Set the Y register to the high-part.
166  SDValue TopPart;
167  if (N->getOpcode() == ISD::SDIV) {
168  TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
169  CurDAG->getTargetConstant(31, dl, MVT::i32)),
170  0);
171  } else {
172  TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
173  }
174  TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
175  SDValue())
176  .getValue(1);
177 
178  // FIXME: Handle div by immediate.
179  unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
180  return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS,
181  TopPart);
182  }
183  case ISD::MULHU:
184  case ISD::MULHS: {
185  // FIXME: Handle mul by immediate.
186  SDValue MulLHS = N->getOperand(0);
187  SDValue MulRHS = N->getOperand(1);
188  unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
189  SDNode *Mul =
190  CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MulLHS, MulRHS);
191  SDValue ResultHigh = SDValue(Mul, 1);
192  ReplaceUses(SDValue(N, 0), ResultHigh);
193  return nullptr;
194  }
195  }
196 
197  return SelectCode(N);
198 }
199 
200 
201 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
202 /// inline asm expressions.
203 bool
204 SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
205  unsigned ConstraintID,
206  std::vector<SDValue> &OutOps) {
207  SDValue Op0, Op1;
208  switch (ConstraintID) {
209  default: return true;
211  case InlineAsm::Constraint_m: // memory
212  if (!SelectADDRrr(Op, Op0, Op1))
213  SelectADDRri(Op, Op0, Op1);
214  break;
215  }
216 
217  OutOps.push_back(Op0);
218  OutOps.push_back(Op1);
219  return false;
220 }
221 
222 /// createSparcISelDag - This pass converts a legalized DAG into a
223 /// SPARC-specific DAG, ready for instruction scheduling.
224 ///
226  return new SparcDAGToDAGISel(TM);
227 }
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:122
const SDValue & getOperand(unsigned Num) const
void setNodeId(int Id)
Set unique node id.
#define R2(n)
GlobalBaseReg - On Darwin, this node represents the result of the mflr at function entry...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:191
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
FunctionPass * createSparcISelDag(SparcTargetMachine &TM)
createSparcISelDag - This pass converts a legalized DAG into a SPARC-specific DAG, ready for instruction scheduling.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
#define N
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:314