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