[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Target / Mips / MipsMCInstLower.cpp
blobfd984058a2bf5d879260a6a568aaefa17a927e86
1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code to lower Mips MachineInstrs to their corresponding
10 // MCInst records.
12 //===----------------------------------------------------------------------===//
14 #include "MipsMCInstLower.h"
15 #include "MCTargetDesc/MipsBaseInfo.h"
16 #include "MCTargetDesc/MipsMCExpr.h"
17 #include "MipsAsmPrinter.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineOperand.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include <cassert>
26 using namespace llvm;
28 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
29 : AsmPrinter(asmprinter) {}
31 void MipsMCInstLower::Initialize(MCContext *C) {
32 Ctx = C;
35 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
36 MachineOperandType MOTy,
37 unsigned Offset) const {
38 MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
39 MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
40 bool IsGpOff = false;
41 const MCSymbol *Symbol;
43 switch(MO.getTargetFlags()) {
44 default:
45 llvm_unreachable("Invalid target flag!");
46 case MipsII::MO_NO_FLAG:
47 break;
48 case MipsII::MO_GPREL:
49 TargetKind = MipsMCExpr::MEK_GPREL;
50 break;
51 case MipsII::MO_GOT_CALL:
52 TargetKind = MipsMCExpr::MEK_GOT_CALL;
53 break;
54 case MipsII::MO_GOT:
55 TargetKind = MipsMCExpr::MEK_GOT;
56 break;
57 case MipsII::MO_ABS_HI:
58 TargetKind = MipsMCExpr::MEK_HI;
59 break;
60 case MipsII::MO_ABS_LO:
61 TargetKind = MipsMCExpr::MEK_LO;
62 break;
63 case MipsII::MO_TLSGD:
64 TargetKind = MipsMCExpr::MEK_TLSGD;
65 break;
66 case MipsII::MO_TLSLDM:
67 TargetKind = MipsMCExpr::MEK_TLSLDM;
68 break;
69 case MipsII::MO_DTPREL_HI:
70 TargetKind = MipsMCExpr::MEK_DTPREL_HI;
71 break;
72 case MipsII::MO_DTPREL_LO:
73 TargetKind = MipsMCExpr::MEK_DTPREL_LO;
74 break;
75 case MipsII::MO_GOTTPREL:
76 TargetKind = MipsMCExpr::MEK_GOTTPREL;
77 break;
78 case MipsII::MO_TPREL_HI:
79 TargetKind = MipsMCExpr::MEK_TPREL_HI;
80 break;
81 case MipsII::MO_TPREL_LO:
82 TargetKind = MipsMCExpr::MEK_TPREL_LO;
83 break;
84 case MipsII::MO_GPOFF_HI:
85 TargetKind = MipsMCExpr::MEK_HI;
86 IsGpOff = true;
87 break;
88 case MipsII::MO_GPOFF_LO:
89 TargetKind = MipsMCExpr::MEK_LO;
90 IsGpOff = true;
91 break;
92 case MipsII::MO_GOT_DISP:
93 TargetKind = MipsMCExpr::MEK_GOT_DISP;
94 break;
95 case MipsII::MO_GOT_HI16:
96 TargetKind = MipsMCExpr::MEK_GOT_HI16;
97 break;
98 case MipsII::MO_GOT_LO16:
99 TargetKind = MipsMCExpr::MEK_GOT_LO16;
100 break;
101 case MipsII::MO_GOT_PAGE:
102 TargetKind = MipsMCExpr::MEK_GOT_PAGE;
103 break;
104 case MipsII::MO_GOT_OFST:
105 TargetKind = MipsMCExpr::MEK_GOT_OFST;
106 break;
107 case MipsII::MO_HIGHER:
108 TargetKind = MipsMCExpr::MEK_HIGHER;
109 break;
110 case MipsII::MO_HIGHEST:
111 TargetKind = MipsMCExpr::MEK_HIGHEST;
112 break;
113 case MipsII::MO_CALL_HI16:
114 TargetKind = MipsMCExpr::MEK_CALL_HI16;
115 break;
116 case MipsII::MO_CALL_LO16:
117 TargetKind = MipsMCExpr::MEK_CALL_LO16;
118 break;
119 case MipsII::MO_JALR:
120 return MCOperand();
123 switch (MOTy) {
124 case MachineOperand::MO_MachineBasicBlock:
125 Symbol = MO.getMBB()->getSymbol();
126 break;
128 case MachineOperand::MO_GlobalAddress:
129 Symbol = AsmPrinter.getSymbol(MO.getGlobal());
130 Offset += MO.getOffset();
131 break;
133 case MachineOperand::MO_BlockAddress:
134 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
135 Offset += MO.getOffset();
136 break;
138 case MachineOperand::MO_ExternalSymbol:
139 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
140 Offset += MO.getOffset();
141 break;
143 case MachineOperand::MO_MCSymbol:
144 Symbol = MO.getMCSymbol();
145 Offset += MO.getOffset();
146 break;
148 case MachineOperand::MO_JumpTableIndex:
149 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
150 break;
152 case MachineOperand::MO_ConstantPoolIndex:
153 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
154 Offset += MO.getOffset();
155 break;
157 default:
158 llvm_unreachable("<unknown operand type>");
161 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
163 if (Offset) {
164 // Assume offset is never negative.
165 assert(Offset > 0);
167 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
168 *Ctx);
171 if (IsGpOff)
172 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
173 else if (TargetKind != MipsMCExpr::MEK_None)
174 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
176 return MCOperand::createExpr(Expr);
179 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
180 unsigned offset) const {
181 MachineOperandType MOTy = MO.getType();
183 switch (MOTy) {
184 default: llvm_unreachable("unknown operand type");
185 case MachineOperand::MO_Register:
186 // Ignore all implicit register operands.
187 if (MO.isImplicit()) break;
188 return MCOperand::createReg(MO.getReg());
189 case MachineOperand::MO_Immediate:
190 return MCOperand::createImm(MO.getImm() + offset);
191 case MachineOperand::MO_MachineBasicBlock:
192 case MachineOperand::MO_GlobalAddress:
193 case MachineOperand::MO_ExternalSymbol:
194 case MachineOperand::MO_MCSymbol:
195 case MachineOperand::MO_JumpTableIndex:
196 case MachineOperand::MO_ConstantPoolIndex:
197 case MachineOperand::MO_BlockAddress:
198 return LowerSymbolOperand(MO, MOTy, offset);
199 case MachineOperand::MO_RegisterMask:
200 break;
203 return MCOperand();
206 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
207 MachineBasicBlock *BB2,
208 MipsMCExpr::MipsExprKind Kind) const {
209 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
210 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
211 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
213 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
216 void MipsMCInstLower::
217 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
218 OutMI.setOpcode(Mips::LUi);
220 // Lower register operand.
221 OutMI.addOperand(LowerOperand(MI->getOperand(0)));
223 MipsMCExpr::MipsExprKind Kind;
224 unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
225 switch (TargetFlags) {
226 case MipsII::MO_HIGHEST:
227 Kind = MipsMCExpr::MEK_HIGHEST;
228 break;
229 case MipsII::MO_HIGHER:
230 Kind = MipsMCExpr::MEK_HIGHER;
231 break;
232 case MipsII::MO_ABS_HI:
233 Kind = MipsMCExpr::MEK_HI;
234 break;
235 case MipsII::MO_ABS_LO:
236 Kind = MipsMCExpr::MEK_LO;
237 break;
238 default:
239 report_fatal_error("Unexpected flags for lowerLongBranchLUi");
242 if (MI->getNumOperands() == 2) {
243 const MCExpr *Expr =
244 MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
245 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
246 OutMI.addOperand(MCOperand::createExpr(MipsExpr));
247 } else if (MI->getNumOperands() == 3) {
248 // Create %hi($tgt-$baltgt).
249 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
250 MI->getOperand(2).getMBB(), Kind));
254 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
255 MCInst &OutMI, int Opcode) const {
256 OutMI.setOpcode(Opcode);
258 MipsMCExpr::MipsExprKind Kind;
259 unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
260 switch (TargetFlags) {
261 case MipsII::MO_HIGHEST:
262 Kind = MipsMCExpr::MEK_HIGHEST;
263 break;
264 case MipsII::MO_HIGHER:
265 Kind = MipsMCExpr::MEK_HIGHER;
266 break;
267 case MipsII::MO_ABS_HI:
268 Kind = MipsMCExpr::MEK_HI;
269 break;
270 case MipsII::MO_ABS_LO:
271 Kind = MipsMCExpr::MEK_LO;
272 break;
273 default:
274 report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
277 // Lower two register operands.
278 for (unsigned I = 0, E = 2; I != E; ++I) {
279 const MachineOperand &MO = MI->getOperand(I);
280 OutMI.addOperand(LowerOperand(MO));
283 if (MI->getNumOperands() == 3) {
284 // Lower register operand.
285 const MCExpr *Expr =
286 MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
287 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
288 OutMI.addOperand(MCOperand::createExpr(MipsExpr));
289 } else if (MI->getNumOperands() == 4) {
290 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
291 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
292 MI->getOperand(3).getMBB(), Kind));
296 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
297 MCInst &OutMI) const {
298 switch (MI->getOpcode()) {
299 default:
300 return false;
301 case Mips::LONG_BRANCH_LUi:
302 case Mips::LONG_BRANCH_LUi2Op:
303 case Mips::LONG_BRANCH_LUi2Op_64:
304 lowerLongBranchLUi(MI, OutMI);
305 return true;
306 case Mips::LONG_BRANCH_ADDiu:
307 case Mips::LONG_BRANCH_ADDiu2Op:
308 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
309 return true;
310 case Mips::LONG_BRANCH_DADDiu:
311 case Mips::LONG_BRANCH_DADDiu2Op:
312 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
313 return true;
317 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
318 if (lowerLongBranch(MI, OutMI))
319 return;
321 OutMI.setOpcode(MI->getOpcode());
323 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
324 const MachineOperand &MO = MI->getOperand(i);
325 MCOperand MCOp = LowerOperand(MO);
327 if (MCOp.isValid())
328 OutMI.addOperand(MCOp);