LLVM  4.0.0
Mips16ISelDAGToDAG.cpp
Go to the documentation of this file.
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"
16 #include "Mips.h"
17 #include "MipsMachineFunction.h"
18 #include "MipsRegisterInfo.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"
34 using namespace llvm;
35 
36 #define DEBUG_TYPE "mips-isel"
37 
38 bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
39  Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget());
40  if (!Subtarget->inMips16Mode())
41  return false;
43 }
44 /// Select multiply instructions.
45 std::pair<SDNode *, SDNode *>
46 Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty,
47  bool HasLo, bool HasHi) {
48  SDNode *Lo = nullptr, *Hi = nullptr;
49  SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
50  N->getOperand(1));
51  SDValue InFlag = SDValue(Mul, 0);
52 
53  if (HasLo) {
54  unsigned Opcode = Mips::Mflo16;
55  Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag);
56  InFlag = SDValue(Lo, 1);
57  }
58  if (HasHi) {
59  unsigned Opcode = Mips::Mfhi16;
60  Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag);
61  }
62  return std::make_pair(Lo, Hi);
63 }
64 
65 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
67 
68  if (!MipsFI->globalBaseRegSet())
69  return;
70 
71  MachineBasicBlock &MBB = MF.front();
75  DebugLoc DL;
76  unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg();
77  const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass;
78 
79  V0 = RegInfo.createVirtualRegister(RC);
80  V1 = RegInfo.createVirtualRegister(RC);
81  V2 = RegInfo.createVirtualRegister(RC);
82 
83 
84  BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0)
85  .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
86  BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1)
87  .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
88 
89  BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16);
90  BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
91  .addReg(V1)
92  .addReg(V2);
93 }
94 
95 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
96  initGlobalBaseReg(MF);
97 }
98 
99 bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base,
100  SDValue &Offset) {
101  SDLoc DL(Addr);
102  EVT ValTy = Addr.getValueType();
103 
104  // if Address is FI, get the TargetFrameIndex.
105  if (SPAllowed) {
106  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
107  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
108  Offset = CurDAG->getTargetConstant(0, DL, ValTy);
109  return true;
110  }
111  }
112  // on PIC code Load GA
113  if (Addr.getOpcode() == MipsISD::Wrapper) {
114  Base = Addr.getOperand(0);
115  Offset = Addr.getOperand(1);
116  return true;
117  }
118  if (!TM.isPositionIndependent()) {
119  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
121  return false;
122  }
123  // Addresses of the form FI+const or FI|const
124  if (CurDAG->isBaseWithConstantOffset(Addr)) {
126  if (isInt<16>(CN->getSExtValue())) {
127  // If the first operand is a FI, get the TargetFI Node
128  if (SPAllowed) {
129  if (FrameIndexSDNode *FIN =
130  dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
131  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
132  Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
133  return true;
134  }
135  }
136 
137  Base = Addr.getOperand(0);
138  Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
139  return true;
140  }
141  }
142  // Operand is a result from an ADD.
143  if (Addr.getOpcode() == ISD::ADD) {
144  // When loading from constant pools, load the lower address part in
145  // the instruction itself. Example, instead of:
146  // lui $2, %hi($CPI1_0)
147  // addiu $2, $2, %lo($CPI1_0)
148  // lwc1 $f0, 0($2)
149  // Generate:
150  // lui $2, %hi($CPI1_0)
151  // lwc1 $f0, %lo($CPI1_0)($2)
152  if (Addr.getOperand(1).getOpcode() == MipsISD::Lo ||
153  Addr.getOperand(1).getOpcode() == MipsISD::GPRel) {
154  SDValue Opnd0 = Addr.getOperand(1).getOperand(0);
155  if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
156  isa<JumpTableSDNode>(Opnd0)) {
157  Base = Addr.getOperand(0);
158  Offset = Opnd0;
159  return true;
160  }
161  }
162  }
163  Base = Addr;
164  Offset = CurDAG->getTargetConstant(0, DL, ValTy);
165  return true;
166 }
167 
168 bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
169  SDValue &Offset) {
170  return selectAddr(false, Addr, Base, Offset);
171 }
172 
173 bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
174  SDValue &Offset) {
175  return selectAddr(true, Addr, Base, Offset);
176 }
177 
178 /// Select instructions not customized! Used for
179 /// expanded, promoted and normal instructions
180 bool Mips16DAGToDAGISel::trySelect(SDNode *Node) {
181  unsigned Opcode = Node->getOpcode();
182  SDLoc DL(Node);
183 
184  ///
185  // Instruction Selection not handled by the auto-generated
186  // tablegen selection should be handled here.
187  ///
188  EVT NodeTy = Node->getValueType(0);
189  unsigned MultOpc;
190 
191  switch (Opcode) {
192  default:
193  break;
194 
195  case ISD::SUBE:
196  case ISD::ADDE: {
197  SDValue InFlag = Node->getOperand(2), CmpLHS;
198  unsigned Opc = InFlag.getOpcode();
199  (void)Opc;
200  assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
201  (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
202  "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
203 
204  unsigned MOp;
205  if (Opcode == ISD::ADDE) {
206  CmpLHS = InFlag.getValue(0);
207  MOp = Mips::AdduRxRyRz16;
208  } else {
209  CmpLHS = InFlag.getOperand(0);
210  MOp = Mips::SubuRxRyRz16;
211  }
212 
213  SDValue Ops[] = {CmpLHS, InFlag.getOperand(1)};
214 
215  SDValue LHS = Node->getOperand(0);
216  SDValue RHS = Node->getOperand(1);
217 
218  EVT VT = LHS.getValueType();
219 
220  unsigned Sltu_op = Mips::SltuRxRyRz16;
221  SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops);
222  unsigned Addu_op = Mips::AdduRxRyRz16;
223  SDNode *AddCarry =
224  CurDAG->getMachineNode(Addu_op, DL, VT, SDValue(Carry, 0), RHS);
225 
226  CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0));
227  return true;
228  }
229 
230  /// Mul with two results
231  case ISD::SMUL_LOHI:
232  case ISD::UMUL_LOHI: {
233  MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16);
234  std::pair<SDNode *, SDNode *> LoHi =
235  selectMULT(Node, MultOpc, DL, NodeTy, true, true);
236  if (!SDValue(Node, 0).use_empty())
237  ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
238 
239  if (!SDValue(Node, 1).use_empty())
240  ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
241 
242  CurDAG->RemoveDeadNode(Node);
243  return true;
244  }
245 
246  case ISD::MULHS:
247  case ISD::MULHU: {
248  MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16);
249  auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true);
250  ReplaceNode(Node, LoHi.second);
251  return true;
252  }
253  }
254 
255  return false;
256 }
257 
259  CodeGenOpt::Level OptLevel) {
260  return new Mips16DAGToDAGISel(TM, OptLevel);
261 }
SDValue getValue(unsigned R) const
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:219
const MipsInstrInfo * getInstrInfo() const override
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:131
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:271
A debug info location.
Definition: DebugLoc.h:34
const SDValue & getOperand(unsigned Num) const
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.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s), MachineInstr opcode, and operands.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol address.
Definition: MipsBaseInfo.h:52
const MachineBasicBlock & front() const
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:535
MachineBasicBlock * MBB
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:487
TargetInstrInfo - Interface to description of machine instruction set.
MachineRegisterInfo * RegInfo
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const MipsSubtarget * Subtarget
Keep a pointer to the MipsSubtarget around so that we can make the right decision when generating cod...
const SDValue & getOperand(unsigned i) const
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:228
uint32_t Offset
bool isPositionIndependent() const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
FunctionPass * createMips16ISelDag(MipsTargetMachine &TM, CodeGenOpt::Level OptLevel)
bool inMips16Mode() const
EVT - Extended Value Type.
Definition: ValueTypes.h:31
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side...
SDNode * SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type...
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
int64_t getSExtValue() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition: ISDOpcodes.h:205
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
EVT getValueType() const
Return the ValueType of the referenced return value.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const TargetInstrInfo * TII
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
uint64_t getZExtValue() const
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:326