blob: 5d49b0140741d9d9fac1f1d5d64f9a49f60c0e43 [file] [log] [blame]
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07001//===- subzero/src/IceTargetLoweringMIPS32.h - MIPS32 lowering ---*- C++-*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the TargetLoweringMIPS32 class, which implements the
Andrew Scull9612d322015-07-06 14:53:25 -070012/// TargetLowering interface for the MIPS 32-bit architecture.
13///
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
17#define SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
18
John Porto53611e22015-12-30 07:30:10 -080019#include "IceAssemblerMIPS32.h"
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070020#include "IceDefs.h"
21#include "IceInstMIPS32.h"
22#include "IceRegistersMIPS32.h"
23#include "IceTargetLowering.h"
24
25namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080026namespace MIPS32 {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070027
28class TargetMIPS32 : public TargetLowering {
29 TargetMIPS32() = delete;
30 TargetMIPS32(const TargetMIPS32 &) = delete;
31 TargetMIPS32 &operator=(const TargetMIPS32 &) = delete;
32
33public:
John Porto53611e22015-12-30 07:30:10 -080034 ~TargetMIPS32() override = default;
35
Karl Schimpf5403f5d2016-01-15 11:07:46 -080036 static void staticInit(GlobalContext *Ctx);
Jim Stichnoth467ffe52016-03-29 15:01:06 -070037 static bool shouldBePooled(const Constant *C) {
Mohit Bhakkadd1e97772016-07-07 05:07:35 -070038 if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) {
39 return !Utils::isPositiveZero(ConstDouble->getValue());
40 }
41 if (llvm::isa<ConstantFloat>(C))
42 return true;
Jim Stichnoth467ffe52016-03-29 15:01:06 -070043 return false;
44 }
John Porto53611e22015-12-30 07:30:10 -080045 static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
46 return makeUnique<TargetMIPS32>(Func);
47 }
48
49 std::unique_ptr<::Ice::Assembler> createAssembler() const override {
50 return makeUnique<MIPS32::AssemblerMIPS32>();
51 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070052
Sagar Thakur5cce7612016-05-24 06:25:50 -070053 void initNodeForLowering(CfgNode *Node) override {
54 Computations.forgetProducers();
55 Computations.recordProducers(Node);
56 Computations.dump(Func);
57 }
58
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070059 void translateOm1() override;
60 void translateO2() override;
Reed Kotler04bca5a2016-02-03 14:40:47 -080061 bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070062
63 SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080064 Variable *getPhysicalRegister(RegNumT RegNum,
65 Type Ty = IceType_void) override;
Jim Stichnoth467ffe52016-03-29 15:01:06 -070066 const char *getRegName(RegNumT RegNum, Type Ty) const override;
John Portoe82b5602016-02-24 15:58:55 -080067 SmallBitVector getRegisterSet(RegSetMask Include,
68 RegSetMask Exclude) const override;
69 const SmallBitVector &
Jim Stichnothc59288b2015-11-09 11:38:40 -080070 getRegistersForVariable(const Variable *Var) const override {
71 RegClass RC = Var->getRegClass();
72 assert(RC < RC_Target);
73 return TypeToRegisterSet[RC];
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070074 }
John Portoe82b5602016-02-24 15:58:55 -080075 const SmallBitVector &
Jim Stichnothb40595a2016-01-29 06:14:31 -080076 getAllRegistersForVariable(const Variable *Var) const override {
77 RegClass RC = Var->getRegClass();
78 assert(RC < RC_Target);
79 return TypeToRegisterSetUnfiltered[RC];
80 }
John Portoe82b5602016-02-24 15:58:55 -080081 const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
John Portobb0a5fe2015-09-04 11:23:41 -070082 return RegisterAliases[Reg];
83 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070084 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -080085 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080086 RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
87 RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
88 RegNumT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -080089 return UsesFramePointer ? getFrameReg() : getStackReg();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070090 }
91 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -070092 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
93 // are rounded up to 4 bytes.
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070094 return (typeWidthInBytes(Ty) + 3) & ~3;
95 }
Sagar Thakur1afb4832016-06-16 15:30:24 -070096 uint32_t getStackAlignment() const override;
David Sehr2f3b8ec2015-11-16 16:51:39 -080097 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
Sagar Thakur1afb4832016-06-16 15:30:24 -070098 FixedAllocaSizeBytes = Size;
99 assert(llvm::isPowerOf2_32(Align));
100 FixedAllocaAlignBytes = Align;
101 PrologEmitsFixedAllocas = true;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800102 }
103 int32_t getFrameFixedAllocaOffset() const override {
104 // TODO(sehr): Implement fixed stack layout.
105 llvm::report_fatal_error("Not yet implemented");
106 return 0;
107 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700108
Sagar Thakur1afb4832016-06-16 15:30:24 -0700109 uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
110
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700111 bool shouldSplitToVariable64On32(Type Ty) const override {
112 return Ty == IceType_i64;
113 }
114
Andrew Scull87f80c12015-07-20 10:19:16 -0700115 // TODO(ascull): what is the best size of MIPS?
116 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700117 void emitJumpTable(const Cfg *Func,
118 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700119
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700120 void emitVariable(const Variable *Var) const override;
121
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700122 void emit(const ConstantInteger32 *C) const final {
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700123 if (!BuildDefs::dump())
124 return;
125 Ostream &Str = Ctx->getStrEmit();
126 Str << C->getValue();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700127 }
128 void emit(const ConstantInteger64 *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700129 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700130 llvm::report_fatal_error("Not yet implemented");
131 }
132 void emit(const ConstantFloat *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700133 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700134 llvm::report_fatal_error("Not yet implemented");
135 }
136 void emit(const ConstantDouble *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700137 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700138 llvm::report_fatal_error("Not yet implemented");
139 }
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800140 void emit(const ConstantUndef *C) const final {
141 (void)C;
142 llvm::report_fatal_error("Not yet implemented");
143 }
144 void emit(const ConstantRelocatable *C) const final {
145 (void)C;
146 llvm::report_fatal_error("Not yet implemented");
147 }
Reed Kotler37af5b02015-11-05 17:07:19 -0800148
149 // The following are helpers that insert lowered MIPS32 instructions with
150 // minimal syntactic overhead, so that the lowering code can look as close to
151 // assembly as practical.
152 void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800153 Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800154 }
155
Reed Kotler00e36042016-02-01 20:52:19 -0800156 void _addu(Variable *Dest, Variable *Src0, Variable *Src1) {
157 Context.insert<InstMIPS32Addu>(Dest, Src0, Src1);
158 }
159
Reed Kotler37af5b02015-11-05 17:07:19 -0800160 void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800161 Context.insert<InstMIPS32And>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800162 }
163
Sagar Thakur38dcb592016-05-09 11:57:59 -0700164 void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
165 Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
166 }
167
Reed Kotler3fe4b572016-02-23 18:59:43 -0800168 void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
169
Sagar Thakur5cce7612016-05-24 06:25:50 -0700170 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
171 Operand *Src1, CondMIPS32::Cond Condition) {
172 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1,
173 Condition);
174 }
175
176 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
177 CondMIPS32::Cond Condition) {
178 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Condition);
179 }
180
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700181 void _ret(Variable *RA, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800182 Context.insert<InstMIPS32Ret>(RA, Src0);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700183 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700184
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700185 void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
186 Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
187 }
188
189 void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
190 Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
191 }
192
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700193 void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800194 Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700195 }
196
Srdjan Obucina418135a2016-06-02 06:47:06 -0700197 void _cvt_d_l(Variable *Dest, Variable *Src) {
198 Context.insert<InstMIPS32Cvt_d_l>(Dest, Src);
199 }
200
201 void _cvt_d_s(Variable *Dest, Variable *Src) {
202 Context.insert<InstMIPS32Cvt_d_s>(Dest, Src);
203 }
204
205 void _cvt_d_w(Variable *Dest, Variable *Src) {
206 Context.insert<InstMIPS32Cvt_d_w>(Dest, Src);
207 }
208
209 void _cvt_s_d(Variable *Dest, Variable *Src) {
210 Context.insert<InstMIPS32Cvt_s_d>(Dest, Src);
211 }
212
213 void _cvt_s_l(Variable *Dest, Variable *Src) {
214 Context.insert<InstMIPS32Cvt_s_l>(Dest, Src);
215 }
216
217 void _cvt_s_w(Variable *Dest, Variable *Src) {
218 Context.insert<InstMIPS32Cvt_s_w>(Dest, Src);
219 }
220
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700221 void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
222 Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
223 }
224
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700225 void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
226 Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
227 }
228
229 void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
230 Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
231 }
232
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700233 void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
234 Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
235 }
236
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700237 void _ldc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
238 Context.insert<InstMIPS32Ldc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700239 }
240
Sagar Thakur633394c2016-06-25 08:34:10 -0700241 void _lw(Variable *Value, OperandMIPS32Mem *Mem) {
242 Context.insert<InstMIPS32Lw>(Value, Mem);
243 }
244
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700245 void _lwc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
246 Context.insert<InstMIPS32Lwc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700247 }
248
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700249 void _lui(Variable *Dest, Operand *Src, RelocOp Reloc = RO_No) {
250 Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700251 }
252
253 void _mov(Variable *Dest, Operand *Src0) {
254 assert(Dest != nullptr);
255 // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
256 if (llvm::isa<ConstantRelocatable>(Src0)) {
John Porto1d937a82015-12-17 06:19:34 -0800257 Context.insert<InstMIPS32La>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700258 } else {
John Porto1d937a82015-12-17 06:19:34 -0800259 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700260 if (Instr->isMultiDest()) {
261 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
262 // fake-def for Instr.DestHi here.
263 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800264 Context.insert<InstFakeDef>(Instr->getDestHi());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700265 }
266 }
267 }
268
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700269 void _mov_d(Variable *Dest, Variable *Src) {
270 Context.insert<InstMIPS32Mov_d>(Dest, Src);
271 }
272
273 void _mov_s(Variable *Dest, Variable *Src) {
274 Context.insert<InstMIPS32Mov_s>(Dest, Src);
275 }
276
277 void _mfc1(Variable *Dest, Variable *Src) {
278 Context.insert<InstMIPS32Mfc1>(Dest, Src);
279 }
280
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800281 void _mfhi(Variable *Dest, Operand *Src) {
282 Context.insert<InstMIPS32Mfhi>(Dest, Src);
283 }
284
285 void _mflo(Variable *Dest, Operand *Src) {
286 Context.insert<InstMIPS32Mflo>(Dest, Src);
287 }
288
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700289 void _mtc1(Variable *Dest, Variable *Src) {
290 Context.insert<InstMIPS32Mtc1>(Dest, Src);
291 }
292
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800293 void _mthi(Variable *Dest, Operand *Src) {
294 Context.insert<InstMIPS32Mthi>(Dest, Src);
295 }
296
297 void _mtlo(Variable *Dest, Operand *Src) {
298 Context.insert<InstMIPS32Mtlo>(Dest, Src);
299 }
300
Reed Kotler37af5b02015-11-05 17:07:19 -0800301 void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800302 Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800303 }
304
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700305 void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
306 Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
307 }
308
309 void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
310 Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
311 }
312
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800313 void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
314 Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
315 }
316
317 void _multu(Variable *Dest, Variable *Src0, Variable *Src1) {
318 Context.insert<InstMIPS32Multu>(Dest, Src0, Src1);
319 }
320
Reed Kotler37af5b02015-11-05 17:07:19 -0800321 void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800322 Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800323 }
324
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700325 void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800326 Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700327 }
328
Srdjan Obucina418135a2016-06-02 06:47:06 -0700329 void _sdc1(Variable *Value, OperandMIPS32Mem *Mem) {
330 Context.insert<InstMIPS32Sdc1>(Value, Mem);
331 }
332
Sagar Thakur38dcb592016-05-09 11:57:59 -0700333 void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
334 Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
335 }
336
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700337 void _sllv(Variable *Dest, Variable *Src0, Variable *Src1) {
338 Context.insert<InstMIPS32Sllv>(Dest, Src0, Src1);
339 }
340
Sagar Thakur1a478b12016-04-25 08:39:19 -0700341 void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
342 Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
343 }
344
345 void _slti(Variable *Dest, Variable *Src, uint32_t Imm) {
346 Context.insert<InstMIPS32Slti>(Dest, Src, Imm);
347 }
348
349 void _sltiu(Variable *Dest, Variable *Src, uint32_t Imm) {
350 Context.insert<InstMIPS32Sltiu>(Dest, Src, Imm);
Reed Kotler37af5b02015-11-05 17:07:19 -0800351 }
352
Reed Kotler00e36042016-02-01 20:52:19 -0800353 void _sltu(Variable *Dest, Variable *Src0, Variable *Src1) {
354 Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
355 }
356
Sagar Thakur38dcb592016-05-09 11:57:59 -0700357 void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
358 Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
359 }
360
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700361 void _srav(Variable *Dest, Variable *Src0, Variable *Src1) {
362 Context.insert<InstMIPS32Srav>(Dest, Src0, Src1);
363 }
364
365 void _srl(Variable *Dest, Variable *Src, uint32_t Imm) {
366 Context.insert<InstMIPS32Srl>(Dest, Src, Imm);
367 }
368
369 void _srlv(Variable *Dest, Variable *Src0, Variable *Src1) {
370 Context.insert<InstMIPS32Srlv>(Dest, Src0, Src1);
371 }
372
Sagar Thakur1a478b12016-04-25 08:39:19 -0700373 void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
374 Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
375 }
376
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700377 void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
378 Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
379 }
380
381 void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
382 Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
383 }
384
Reed Kotler00e36042016-02-01 20:52:19 -0800385 void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
386 Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
387 }
388
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700389 void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
390 Context.insert<InstMIPS32Sw>(Value, Mem);
391 }
392
Srdjan Obucina418135a2016-06-02 06:47:06 -0700393 void _swc1(Variable *Value, OperandMIPS32Mem *Mem) {
394 Context.insert<InstMIPS32Swc1>(Value, Mem);
395 }
396
397 void _trunc_l_d(Variable *Dest, Variable *Src) {
398 Context.insert<InstMIPS32Trunc_l_d>(Dest, Src);
399 }
400
401 void _trunc_l_s(Variable *Dest, Variable *Src) {
402 Context.insert<InstMIPS32Trunc_l_s>(Dest, Src);
403 }
404
405 void _trunc_w_d(Variable *Dest, Variable *Src) {
406 Context.insert<InstMIPS32Trunc_w_d>(Dest, Src);
407 }
408
409 void _trunc_w_s(Variable *Dest, Variable *Src) {
410 Context.insert<InstMIPS32Trunc_w_s>(Dest, Src);
411 }
412
Reed Kotler37af5b02015-11-05 17:07:19 -0800413 void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800414 Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800415 }
416
Sagar Thakur1a478b12016-04-25 08:39:19 -0700417 void _xori(Variable *Dest, Variable *Src, uint32_t Imm) {
418 Context.insert<InstMIPS32Xori>(Dest, Src, Imm);
419 }
420
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700421 void lowerArguments() override;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700422
423 /// Operand legalization helpers. To deal with address mode constraints,
424 /// the helpers will create a new Operand and emit instructions that
425 /// guarantee that the Operand kind is one of those indicated by the
426 /// LegalMask (a bitmask of allowed kinds). If the input Operand is known
427 /// to already meet the constraints, it may be simply returned as the result,
428 /// without creating any new instructions or operands.
429 enum OperandLegalization {
430 Legal_None = 0,
431 Legal_Reg = 1 << 0, // physical register, not stack location
432 Legal_Imm = 1 << 1,
433 Legal_Mem = 1 << 2,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800434 Legal_Default = ~Legal_None
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700435 };
436 typedef uint32_t LegalMask;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800437 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800438 RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700439
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800440 Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700441
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800442 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700443
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800444 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
Reed Kotler953568f2016-02-17 05:37:01 -0800445
Sagar Thakur1a478b12016-04-25 08:39:19 -0700446 Variable *getZero() {
447 return getPhysicalRegister(RegMIPS32::Reg_ZERO, IceType_i32);
448 }
449
Reed Kotler953568f2016-02-17 05:37:01 -0800450 Variable *I32Reg(RegNumT RegNum = RegNumT()) {
451 return makeReg(IceType_i32, RegNum);
452 }
453
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700454 static Type stackSlotType();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800455 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700456
Sagar Thakur1afb4832016-06-16 15:30:24 -0700457 void unsetIfNonLeafFunc();
458
Sagar Thakura49fce02016-06-13 05:55:00 -0700459 // Iterates over the CFG and determines the maximum outgoing stack arguments
460 // bytes. This information is later used during addProlog() to pre-allocate
461 // the outargs area
462 void findMaxStackOutArgsSize();
463
Sagar Thakur5674c912016-07-14 14:50:37 -0700464 void postLowerLegalization();
465
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700466 void addProlog(CfgNode *Node) override;
467 void addEpilog(CfgNode *Node) override;
468
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700469 // Ensure that a 64-bit Variable has been split into 2 32-bit
470 // Variables, creating them if necessary. This is needed for all
471 // I64 operations.
472 void split64(Variable *Var);
473 Operand *loOperand(Operand *Operand);
474 Operand *hiOperand(Operand *Operand);
475
Sagar Thakura49fce02016-06-13 05:55:00 -0700476 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
477 size_t BasicFrameOffset, size_t *InArgsSizeBytes);
478
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800479 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700480
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700481 /// Helper class that understands the Calling Convention and register
482 /// assignments as per MIPS O32 abi.
483 class CallingConv {
484 CallingConv(const CallingConv &) = delete;
485 CallingConv &operator=(const CallingConv &) = delete;
486
487 public:
488 CallingConv();
489 ~CallingConv() = default;
490
491 /// argInReg returns true if there is a Register available for the requested
492 /// type, and false otherwise. If it returns true, Reg is set to the
493 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
494 /// be an I64 register pair.
495 bool argInReg(Type Ty, uint32_t ArgNo, RegNumT *Reg);
496
497 private:
498 // argInGPR is used to find if any GPR register is available for argument of
499 // type Ty
500 bool argInGPR(Type Ty, RegNumT *Reg);
501 /// argInVFP is to floating-point/vector types what argInGPR is for integer
502 /// types.
503 bool argInVFP(Type Ty, RegNumT *Reg);
504 inline void discardNextGPRAndItsAliases(CfgVector<RegNumT> *Regs);
Mohit Bhakkadbbb5fa72016-06-29 06:51:08 -0700505 inline void alignGPR(CfgVector<RegNumT> *Regs);
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700506 void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
507 SmallBitVector GPRegsUsed;
508 CfgVector<RegNumT> GPRArgs;
509 CfgVector<RegNumT> I64Args;
510
511 void discardUnavailableVFPRegsAndTheirAliases(CfgVector<RegNumT> *Regs);
512 SmallBitVector VFPRegsUsed;
513 CfgVector<RegNumT> FP32Args;
514 CfgVector<RegNumT> FP64Args;
515 // UseFPRegs is a flag indicating if FP registers can be used
516 bool UseFPRegs = false;
517 };
518
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700519protected:
520 explicit TargetMIPS32(Cfg *Func);
521
522 void postLower() override;
523
Reed Kotler04bca5a2016-02-03 14:40:47 -0800524 void lowerAlloca(const InstAlloca *Instr) override;
525 void lowerArithmetic(const InstArithmetic *Instr) override;
526 void lowerInt64Arithmetic(const InstArithmetic *Instr, Variable *Dest,
Reed Kotler00e36042016-02-01 20:52:19 -0800527 Operand *Src0, Operand *Src1);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800528 void lowerAssign(const InstAssign *Instr) override;
529 void lowerBr(const InstBr *Instr) override;
Eric Holk67c7c412016-04-15 13:05:37 -0700530 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800531 void lowerCall(const InstCall *Instr) override;
532 void lowerCast(const InstCast *Instr) override;
533 void lowerExtractElement(const InstExtractElement *Instr) override;
534 void lowerFcmp(const InstFcmp *Instr) override;
535 void lowerIcmp(const InstIcmp *Instr) override;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700536 void lower64Icmp(const InstIcmp *Instr);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800537 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
538 void lowerInsertElement(const InstInsertElement *Instr) override;
539 void lowerLoad(const InstLoad *Instr) override;
540 void lowerPhi(const InstPhi *Instr) override;
541 void lowerRet(const InstRet *Instr) override;
542 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700543 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800544 void lowerStore(const InstStore *Instr) override;
545 void lowerSwitch(const InstSwitch *Instr) override;
546 void lowerUnreachable(const InstUnreachable *Instr) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700547 void prelowerPhis() override;
John Portof4198542015-11-20 14:17:23 -0800548 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override {
549 (void)Instr;
550 return 0;
551 }
John Porto5e0a8a72015-11-20 13:50:36 -0800552 void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700553 void doAddressOptLoad() override;
554 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700555 void randomlyInsertNop(float Probability,
556 RandomNumberGenerator &RNG) override;
557 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800558 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800559 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700560 uint64_t Salt) const override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700561
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700562 OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
563
Sagar Thakur5674c912016-07-14 14:50:37 -0700564 class PostLoweringLegalizer {
565 PostLoweringLegalizer() = delete;
566 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
567 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
568
569 public:
570 explicit PostLoweringLegalizer(TargetMIPS32 *Target)
571 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
572 Target->getFrameOrStackReg())) {}
573
574 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
575 /// if its Source is a Rematerializable variable (this form is used in lieu
576 /// of lea, which is not available in MIPS.)
577 ///
578 /// Moves to memory become store instructions, and moves from memory, loads.
579 void legalizeMov(InstMIPS32Mov *Mov);
580
581 private:
582 /// Creates a new Base register centered around [Base, +/- Offset].
583 Variable *newBaseRegister(Variable *Base, int32_t Offset,
584 RegNumT ScratchRegNum);
585
586 TargetMIPS32 *const Target;
587 Variable *const StackOrFrameReg;
588 };
589
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700590 bool UsesFramePointer = false;
591 bool NeedsStackAlignment = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700592 bool MaybeLeafFunc = true;
593 bool PrologEmitsFixedAllocas = false;
Sagar Thakurc930d592016-07-12 04:06:44 -0700594 bool VariableAllocaUsed = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700595 uint32_t MaxOutArgsSizeBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700596 uint32_t TotalStackSizeBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -0800597 static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
598 static SmallBitVector TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
599 static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
600 SmallBitVector RegsUsed;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700601 VarList PhysicalRegisters[IceType_NUM];
Sagar Thakura49fce02016-06-13 05:55:00 -0700602 VarList PreservedGPRs;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700603 static constexpr uint32_t CHAR_BITS = 8;
604 static constexpr uint32_t INT32_BITS = 32;
Sagar Thakura49fce02016-06-13 05:55:00 -0700605 size_t SpillAreaSizeBytes = 0;
Sagar Thakur1afb4832016-06-16 15:30:24 -0700606 size_t FixedAllocaSizeBytes = 0;
607 size_t FixedAllocaAlignBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700608 size_t PreservedRegsSizeBytes = 0;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700609
610private:
John Porto53611e22015-12-30 07:30:10 -0800611 ENABLE_MAKE_UNIQUE;
Sagar Thakur5cce7612016-05-24 06:25:50 -0700612
613 class ComputationTracker {
614 public:
615 ComputationTracker() = default;
616 ~ComputationTracker() = default;
617
618 void forgetProducers() { KnownComputations.clear(); }
619 void recordProducers(CfgNode *Node);
620
621 const Inst *getProducerOf(const Operand *Opnd) const {
622 auto *Var = llvm::dyn_cast<Variable>(Opnd);
623 if (Var == nullptr) {
624 return nullptr;
625 }
626
627 auto Iter = KnownComputations.find(Var->getIndex());
628 if (Iter == KnownComputations.end()) {
629 return nullptr;
630 }
631
632 return Iter->second.Instr;
633 }
634
635 void dump(const Cfg *Func) const {
636 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
637 return;
638 OstreamLocker L(Func->getContext());
639 Ostream &Str = Func->getContext()->getStrDump();
640 Str << "foldable producer:\n";
641 for (const auto &Computation : KnownComputations) {
642 Str << " ";
643 Computation.second.Instr->dump(Func);
644 Str << "\n";
645 }
646 Str << "\n";
647 }
648
649 private:
650 class ComputationEntry {
651 public:
652 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
653 Inst *const Instr;
654 // Boolean folding is disabled for variables whose live range is multi
655 // block. We conservatively initialize IsLiveOut to true, and set it to
656 // false once we find the end of the live range for the variable defined
657 // by this instruction. If liveness analysis is not performed (e.g., in
658 // Om1 mode) IsLiveOut will never be set to false, and folding will be
659 // disabled.
660 bool IsLiveOut = true;
661 int32_t NumUses = 0;
662 Type ComputationType;
663 };
664
665 // ComputationMap maps a Variable number to a payload identifying which
666 // instruction defined it.
667 using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
668 ComputationMap KnownComputations;
669 };
670
671 ComputationTracker Computations;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700672};
673
John Porto0f86d032015-06-15 07:44:27 -0700674class TargetDataMIPS32 final : public TargetDataLowering {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700675 TargetDataMIPS32() = delete;
676 TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
677 TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
678
679public:
Jan Voungfb792842015-06-11 15:27:50 -0700680 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
681 return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700682 }
683
John Porto8b1a7052015-06-17 13:20:08 -0700684 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700685 const std::string &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700686 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -0700687 void lowerJumpTables() override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700688
689protected:
690 explicit TargetDataMIPS32(GlobalContext *Ctx);
691
692private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700693 ~TargetDataMIPS32() override = default;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700694 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
695};
696
Jan Voungfb792842015-06-11 15:27:50 -0700697class TargetHeaderMIPS32 final : public TargetHeaderLowering {
698 TargetHeaderMIPS32() = delete;
699 TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
700 TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
701
702public:
703 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
704 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
705 }
706
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700707 void lower() override;
708
Jan Voungfb792842015-06-11 15:27:50 -0700709protected:
710 explicit TargetHeaderMIPS32(GlobalContext *Ctx);
711
712private:
713 ~TargetHeaderMIPS32() = default;
714};
715
John Porto4a566862016-01-04 09:33:41 -0800716} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700717} // end of namespace Ice
718
719#endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H