blob: 710e8e75c48e5bf91445694f61bea9a624cb2a65 [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 }
Jaydeep Patilcf9c12f2016-09-20 08:38:11 -070041 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(C)) {
42 return !Utils::isPositiveZero(ConstFloat->getValue());
43 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -070044 return false;
45 }
Nicolas Capens32f9cce2016-10-19 01:24:27 -040046 static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; }
John Porto53611e22015-12-30 07:30:10 -080047 static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
48 return makeUnique<TargetMIPS32>(Func);
49 }
50
51 std::unique_ptr<::Ice::Assembler> createAssembler() const override {
52 return makeUnique<MIPS32::AssemblerMIPS32>();
53 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070054
Sagar Thakur5cce7612016-05-24 06:25:50 -070055 void initNodeForLowering(CfgNode *Node) override {
56 Computations.forgetProducers();
57 Computations.recordProducers(Node);
58 Computations.dump(Func);
59 }
60
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070061 void translateOm1() override;
62 void translateO2() override;
Reed Kotler04bca5a2016-02-03 14:40:47 -080063 bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
Jaydeep Patil958ddb72016-10-03 07:52:48 -070064 void setImplicitRet(Variable *Ret) { ImplicitRet = Ret; }
65 Variable *getImplicitRet() const { return ImplicitRet; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070066 SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080067 Variable *getPhysicalRegister(RegNumT RegNum,
68 Type Ty = IceType_void) override;
Jim Stichnoth467ffe52016-03-29 15:01:06 -070069 const char *getRegName(RegNumT RegNum, Type Ty) const override;
John Portoe82b5602016-02-24 15:58:55 -080070 SmallBitVector getRegisterSet(RegSetMask Include,
71 RegSetMask Exclude) const override;
72 const SmallBitVector &
Jim Stichnothc59288b2015-11-09 11:38:40 -080073 getRegistersForVariable(const Variable *Var) const override {
74 RegClass RC = Var->getRegClass();
75 assert(RC < RC_Target);
76 return TypeToRegisterSet[RC];
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070077 }
John Portoe82b5602016-02-24 15:58:55 -080078 const SmallBitVector &
Jim Stichnothb40595a2016-01-29 06:14:31 -080079 getAllRegistersForVariable(const Variable *Var) const override {
80 RegClass RC = Var->getRegClass();
81 assert(RC < RC_Target);
82 return TypeToRegisterSetUnfiltered[RC];
83 }
John Portoe82b5602016-02-24 15:58:55 -080084 const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
John Portobb0a5fe2015-09-04 11:23:41 -070085 return RegisterAliases[Reg];
86 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070087 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -080088 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080089 RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
90 RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
91 RegNumT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -080092 return UsesFramePointer ? getFrameReg() : getStackReg();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070093 }
Jaydeep Patilec929172016-10-16 07:13:38 -070094 RegNumT getReservedTmpReg() const { return RegMIPS32::Reg_AT; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070095 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -070096 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
97 // are rounded up to 4 bytes.
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070098 return (typeWidthInBytes(Ty) + 3) & ~3;
99 }
Sagar Thakur1afb4832016-06-16 15:30:24 -0700100 uint32_t getStackAlignment() const override;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800101 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
Sagar Thakur1afb4832016-06-16 15:30:24 -0700102 FixedAllocaSizeBytes = Size;
103 assert(llvm::isPowerOf2_32(Align));
104 FixedAllocaAlignBytes = Align;
105 PrologEmitsFixedAllocas = true;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800106 }
107 int32_t getFrameFixedAllocaOffset() const override {
Sagar Thakur46832372016-10-16 07:20:44 -0700108 int32_t FixedAllocaOffset =
109 Utils::applyAlignment(CurrentAllocaOffset, FixedAllocaAlignBytes);
110 return FixedAllocaOffset - MaxOutArgsSizeBytes;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800111 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700112
Sagar Thakur1afb4832016-06-16 15:30:24 -0700113 uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
114
Stefan Maksimovic298d14e2017-01-11 05:58:27 -0800115 uint32_t getFramePointerOffset(uint32_t CurrentOffset,
116 uint32_t Size) const override {
117 (void)Size;
118 return CurrentOffset + MaxOutArgsSizeBytes;
119 }
120
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700121 bool shouldSplitToVariable64On32(Type Ty) const override {
122 return Ty == IceType_i64;
123 }
124
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700125 bool shouldSplitToVariableVecOn32(Type Ty) const override {
126 return isVectorType(Ty);
127 }
128
Andrew Scull87f80c12015-07-20 10:19:16 -0700129 // TODO(ascull): what is the best size of MIPS?
130 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700131 void emitJumpTable(const Cfg *Func,
132 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700133
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700134 void emitVariable(const Variable *Var) const override;
135
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700136 void emit(const ConstantInteger32 *C) const final {
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700137 if (!BuildDefs::dump())
138 return;
139 Ostream &Str = Ctx->getStrEmit();
140 Str << C->getValue();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700141 }
142 void emit(const ConstantInteger64 *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700143 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700144 llvm::report_fatal_error("Not yet implemented");
145 }
146 void emit(const ConstantFloat *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700147 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700148 llvm::report_fatal_error("Not yet implemented");
149 }
150 void emit(const ConstantDouble *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700151 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700152 llvm::report_fatal_error("Not yet implemented");
153 }
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800154 void emit(const ConstantUndef *C) const final {
155 (void)C;
156 llvm::report_fatal_error("Not yet implemented");
157 }
158 void emit(const ConstantRelocatable *C) const final {
159 (void)C;
160 llvm::report_fatal_error("Not yet implemented");
161 }
Reed Kotler37af5b02015-11-05 17:07:19 -0800162
163 // The following are helpers that insert lowered MIPS32 instructions with
164 // minimal syntactic overhead, so that the lowering code can look as close to
165 // assembly as practical.
166 void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800167 Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800168 }
169
Reed Kotler00e36042016-02-01 20:52:19 -0800170 void _addu(Variable *Dest, Variable *Src0, Variable *Src1) {
171 Context.insert<InstMIPS32Addu>(Dest, Src0, Src1);
172 }
173
Reed Kotler37af5b02015-11-05 17:07:19 -0800174 void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800175 Context.insert<InstMIPS32And>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800176 }
177
Sagar Thakur38dcb592016-05-09 11:57:59 -0700178 void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
179 Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
180 }
181
Reed Kotler3fe4b572016-02-23 18:59:43 -0800182 void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
183
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800184 void _br(CfgNode *Target, const InstMIPS32Label *Label) {
185 Context.insert<InstMIPS32Br>(Target, Label);
186 }
187
Sagar Thakur5cce7612016-05-24 06:25:50 -0700188 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
189 Operand *Src1, CondMIPS32::Cond Condition) {
190 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1,
191 Condition);
192 }
193
194 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
195 CondMIPS32::Cond Condition) {
196 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Condition);
197 }
198
Jaydeep Patil29823f12016-08-31 05:10:03 -0700199 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
200 Operand *Src1, const InstMIPS32Label *Label,
201 CondMIPS32::Cond Condition) {
202 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1, Label,
203 Condition);
204 }
205
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700206 void _ret(Variable *RA, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800207 Context.insert<InstMIPS32Ret>(RA, Src0);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700208 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700209
Srdjan Obucina53d05682016-09-10 08:25:37 -0700210 void _abs_d(Variable *Dest, Variable *Src) {
211 Context.insert<InstMIPS32Abs_d>(Dest, Src);
212 }
213
214 void _abs_s(Variable *Dest, Variable *Src) {
215 Context.insert<InstMIPS32Abs_s>(Dest, Src);
216 }
217
Jaydeep Patil130aca72016-10-28 05:30:54 -0700218 void _addi(Variable *Dest, Variable *Src, uint32_t Imm) {
219 Context.insert<InstMIPS32Addi>(Dest, Src, Imm);
220 }
221
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700222 void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
223 Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
224 }
225
226 void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
227 Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
228 }
229
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700230 void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800231 Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700232 }
233
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -0700234 void _addiu(Variable *Dest, Variable *Src0, Operand *Src1, RelocOp Reloc) {
235 Context.insert<InstMIPS32Addiu>(Dest, Src0, Src1, Reloc);
236 }
237
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700238 void _c_eq_d(Variable *Src0, Variable *Src1) {
239 Context.insert<InstMIPS32C_eq_d>(Src0, Src1);
240 }
241
242 void _c_eq_s(Variable *Src0, Variable *Src1) {
243 Context.insert<InstMIPS32C_eq_s>(Src0, Src1);
244 }
245
246 void _c_ole_d(Variable *Src0, Variable *Src1) {
247 Context.insert<InstMIPS32C_ole_d>(Src0, Src1);
248 }
249
250 void _c_ole_s(Variable *Src0, Variable *Src1) {
251 Context.insert<InstMIPS32C_ole_s>(Src0, Src1);
252 }
253
254 void _c_olt_d(Variable *Src0, Variable *Src1) {
255 Context.insert<InstMIPS32C_olt_d>(Src0, Src1);
256 }
257
258 void _c_olt_s(Variable *Src0, Variable *Src1) {
259 Context.insert<InstMIPS32C_olt_s>(Src0, Src1);
260 }
261
262 void _c_ueq_d(Variable *Src0, Variable *Src1) {
263 Context.insert<InstMIPS32C_ueq_d>(Src0, Src1);
264 }
265
266 void _c_ueq_s(Variable *Src0, Variable *Src1) {
267 Context.insert<InstMIPS32C_ueq_s>(Src0, Src1);
268 }
269
270 void _c_ule_d(Variable *Src0, Variable *Src1) {
271 Context.insert<InstMIPS32C_ule_d>(Src0, Src1);
272 }
273
274 void _c_ule_s(Variable *Src0, Variable *Src1) {
275 Context.insert<InstMIPS32C_ule_s>(Src0, Src1);
276 }
277
278 void _c_ult_d(Variable *Src0, Variable *Src1) {
279 Context.insert<InstMIPS32C_ult_d>(Src0, Src1);
280 }
281
282 void _c_ult_s(Variable *Src0, Variable *Src1) {
283 Context.insert<InstMIPS32C_ult_s>(Src0, Src1);
284 }
285
286 void _c_un_d(Variable *Src0, Variable *Src1) {
287 Context.insert<InstMIPS32C_un_d>(Src0, Src1);
288 }
289
290 void _c_un_s(Variable *Src0, Variable *Src1) {
291 Context.insert<InstMIPS32C_un_s>(Src0, Src1);
292 }
293
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700294 void _clz(Variable *Dest, Variable *Src) {
295 Context.insert<InstMIPS32Clz>(Dest, Src);
296 }
297
Srdjan Obucina418135a2016-06-02 06:47:06 -0700298 void _cvt_d_l(Variable *Dest, Variable *Src) {
299 Context.insert<InstMIPS32Cvt_d_l>(Dest, Src);
300 }
301
302 void _cvt_d_s(Variable *Dest, Variable *Src) {
303 Context.insert<InstMIPS32Cvt_d_s>(Dest, Src);
304 }
305
306 void _cvt_d_w(Variable *Dest, Variable *Src) {
307 Context.insert<InstMIPS32Cvt_d_w>(Dest, Src);
308 }
309
310 void _cvt_s_d(Variable *Dest, Variable *Src) {
311 Context.insert<InstMIPS32Cvt_s_d>(Dest, Src);
312 }
313
314 void _cvt_s_l(Variable *Dest, Variable *Src) {
315 Context.insert<InstMIPS32Cvt_s_l>(Dest, Src);
316 }
317
318 void _cvt_s_w(Variable *Dest, Variable *Src) {
319 Context.insert<InstMIPS32Cvt_s_w>(Dest, Src);
320 }
321
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700322 void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
323 Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
324 }
325
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700326 void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
327 Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
328 }
329
330 void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
331 Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
332 }
333
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700334 void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
335 Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
336 }
337
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700338 void _ldc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
339 Context.insert<InstMIPS32Ldc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700340 }
341
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800342 void _ll(Variable *Value, OperandMIPS32Mem *Mem) {
343 Context.insert<InstMIPS32Ll>(Value, Mem);
344 }
345
Sagar Thakur633394c2016-06-25 08:34:10 -0700346 void _lw(Variable *Value, OperandMIPS32Mem *Mem) {
347 Context.insert<InstMIPS32Lw>(Value, Mem);
348 }
349
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700350 void _lwc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
351 Context.insert<InstMIPS32Lwc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700352 }
353
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700354 void _lui(Variable *Dest, Operand *Src, RelocOp Reloc = RO_No) {
355 Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700356 }
357
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700358 void _mfc1(Variable *Dest, Variable *Src) {
359 Context.insert<InstMIPS32Mfc1>(Dest, Src);
360 }
361
362 void _mfhi(Variable *Dest, Operand *Src) {
363 Context.insert<InstMIPS32Mfhi>(Dest, Src);
364 }
365
366 void _mflo(Variable *Dest, Operand *Src) {
367 Context.insert<InstMIPS32Mflo>(Dest, Src);
368 }
369
Sagar Thakurb001cc42016-10-11 23:36:01 -0700370 void _mov(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700371 assert(Dest != nullptr);
372 // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
373 if (llvm::isa<ConstantRelocatable>(Src0)) {
John Porto1d937a82015-12-17 06:19:34 -0800374 Context.insert<InstMIPS32La>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700375 } else {
Sagar Thakurb001cc42016-10-11 23:36:01 -0700376 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
377 if (Instr->getDestHi() != nullptr) {
378 // If DestHi is available, then Dest must be a Variable64On32. We add a
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700379 // fake-def for Instr.DestHi here.
380 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800381 Context.insert<InstFakeDef>(Instr->getDestHi());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700382 }
383 }
384 }
385
Stefan Maksimovicf8c99772016-11-02 05:59:06 -0700386 void _mov_redefined(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
387 if (llvm::isa<ConstantRelocatable>(Src0)) {
388 Context.insert<InstMIPS32La>(Dest, Src0);
389 } else {
390 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
391 Instr->setDestRedefined();
392 if (Instr->getDestHi() != nullptr) {
393 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
394 // fake-def for Instr.DestHi here.
395 assert(llvm::isa<Variable64On32>(Dest));
396 Context.insert<InstFakeDef>(Instr->getDestHi());
397 }
398 }
399 }
400
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -0800401 void _mov_fp64_to_i64(Variable *Dest, Operand *Src, Int64Part Int64HiLo) {
402 assert(Dest != nullptr);
403 Context.insert<InstMIPS32MovFP64ToI64>(Dest, Src, Int64HiLo);
404 }
405
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700406 void _mov_d(Variable *Dest, Variable *Src) {
407 Context.insert<InstMIPS32Mov_d>(Dest, Src);
408 }
409
410 void _mov_s(Variable *Dest, Variable *Src) {
411 Context.insert<InstMIPS32Mov_s>(Dest, Src);
412 }
413
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700414 void _movf(Variable *Dest, Variable *Src0, Operand *FCC) {
415 Context.insert<InstMIPS32Movf>(Dest, Src0, FCC)->setDestRedefined();
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700416 }
417
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700418 void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700419 Context.insert<InstMIPS32Movn>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700420 }
421
422 void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700423 Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700424 }
425
426 void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700427 Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700428 }
429
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700430 void _movt(Variable *Dest, Variable *Src0, Operand *FCC) {
431 Context.insert<InstMIPS32Movt>(Dest, Src0, FCC)->setDestRedefined();
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700432 }
433
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700434 void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700435 Context.insert<InstMIPS32Movz>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700436 }
437
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700438 void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700439 Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1)->setDestRedefined();
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800440 }
441
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700442 void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700443 Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1)->setDestRedefined();
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800444 }
445
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700446 void _mtc1(Variable *Dest, Variable *Src) {
447 Context.insert<InstMIPS32Mtc1>(Dest, Src);
448 }
449
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800450 void _mthi(Variable *Dest, Operand *Src) {
451 Context.insert<InstMIPS32Mthi>(Dest, Src);
452 }
453
454 void _mtlo(Variable *Dest, Operand *Src) {
455 Context.insert<InstMIPS32Mtlo>(Dest, Src);
456 }
457
Reed Kotler37af5b02015-11-05 17:07:19 -0800458 void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800459 Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800460 }
461
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700462 void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
463 Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
464 }
465
466 void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
467 Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
468 }
469
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800470 void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
471 Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
472 }
473
474 void _multu(Variable *Dest, Variable *Src0, Variable *Src1) {
475 Context.insert<InstMIPS32Multu>(Dest, Src0, Src1);
476 }
477
Srdjan Obucina8fbddc62016-09-15 17:26:40 -0700478 void _nop() { Context.insert<InstMIPS32Sll>(getZero(), getZero(), 0); }
479
Srdjan Obucinacadda792016-09-22 11:24:44 -0700480 void _nor(Variable *Dest, Variable *Src0, Variable *Src1) {
481 Context.insert<InstMIPS32Nor>(Dest, Src0, Src1);
482 }
483
484 void _not(Variable *Dest, Variable *Src0) {
485 Context.insert<InstMIPS32Nor>(Dest, Src0, getZero());
486 }
487
Reed Kotler37af5b02015-11-05 17:07:19 -0800488 void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800489 Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800490 }
491
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700492 void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800493 Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700494 }
495
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800496 InstMIPS32Sc *_sc(Variable *Value, OperandMIPS32Mem *Mem) {
497 return Context.insert<InstMIPS32Sc>(Value, Mem);
498 }
499
Srdjan Obucina418135a2016-06-02 06:47:06 -0700500 void _sdc1(Variable *Value, OperandMIPS32Mem *Mem) {
501 Context.insert<InstMIPS32Sdc1>(Value, Mem);
502 }
503
Sagar Thakur38dcb592016-05-09 11:57:59 -0700504 void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
505 Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
506 }
507
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700508 void _sllv(Variable *Dest, Variable *Src0, Variable *Src1) {
509 Context.insert<InstMIPS32Sllv>(Dest, Src0, Src1);
510 }
511
Sagar Thakur1a478b12016-04-25 08:39:19 -0700512 void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
513 Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
514 }
515
516 void _slti(Variable *Dest, Variable *Src, uint32_t Imm) {
517 Context.insert<InstMIPS32Slti>(Dest, Src, Imm);
518 }
519
520 void _sltiu(Variable *Dest, Variable *Src, uint32_t Imm) {
521 Context.insert<InstMIPS32Sltiu>(Dest, Src, Imm);
Reed Kotler37af5b02015-11-05 17:07:19 -0800522 }
523
Reed Kotler00e36042016-02-01 20:52:19 -0800524 void _sltu(Variable *Dest, Variable *Src0, Variable *Src1) {
525 Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
526 }
527
Srdjan Obucina53d05682016-09-10 08:25:37 -0700528 void _sqrt_d(Variable *Dest, Variable *Src) {
529 Context.insert<InstMIPS32Sqrt_d>(Dest, Src);
530 }
531
532 void _sqrt_s(Variable *Dest, Variable *Src) {
533 Context.insert<InstMIPS32Sqrt_s>(Dest, Src);
534 }
535
Sagar Thakur38dcb592016-05-09 11:57:59 -0700536 void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
537 Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
538 }
539
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700540 void _srav(Variable *Dest, Variable *Src0, Variable *Src1) {
541 Context.insert<InstMIPS32Srav>(Dest, Src0, Src1);
542 }
543
544 void _srl(Variable *Dest, Variable *Src, uint32_t Imm) {
545 Context.insert<InstMIPS32Srl>(Dest, Src, Imm);
546 }
547
548 void _srlv(Variable *Dest, Variable *Src0, Variable *Src1) {
549 Context.insert<InstMIPS32Srlv>(Dest, Src0, Src1);
550 }
551
Sagar Thakur1a478b12016-04-25 08:39:19 -0700552 void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
553 Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
554 }
555
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700556 void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
557 Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
558 }
559
560 void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
561 Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
562 }
563
Reed Kotler00e36042016-02-01 20:52:19 -0800564 void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
565 Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
566 }
567
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700568 void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
569 Context.insert<InstMIPS32Sw>(Value, Mem);
570 }
571
Srdjan Obucina418135a2016-06-02 06:47:06 -0700572 void _swc1(Variable *Value, OperandMIPS32Mem *Mem) {
573 Context.insert<InstMIPS32Swc1>(Value, Mem);
574 }
575
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800576 void _sync() { Context.insert<InstMIPS32Sync>(); }
577
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700578 void _teq(Variable *Src0, Variable *Src1, uint32_t TrapCode) {
579 Context.insert<InstMIPS32Teq>(Src0, Src1, TrapCode);
580 }
581
Srdjan Obucina418135a2016-06-02 06:47:06 -0700582 void _trunc_l_d(Variable *Dest, Variable *Src) {
583 Context.insert<InstMIPS32Trunc_l_d>(Dest, Src);
584 }
585
586 void _trunc_l_s(Variable *Dest, Variable *Src) {
587 Context.insert<InstMIPS32Trunc_l_s>(Dest, Src);
588 }
589
590 void _trunc_w_d(Variable *Dest, Variable *Src) {
591 Context.insert<InstMIPS32Trunc_w_d>(Dest, Src);
592 }
593
594 void _trunc_w_s(Variable *Dest, Variable *Src) {
595 Context.insert<InstMIPS32Trunc_w_s>(Dest, Src);
596 }
597
Reed Kotler37af5b02015-11-05 17:07:19 -0800598 void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800599 Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800600 }
601
Sagar Thakur1a478b12016-04-25 08:39:19 -0700602 void _xori(Variable *Dest, Variable *Src, uint32_t Imm) {
603 Context.insert<InstMIPS32Xori>(Dest, Src, Imm);
604 }
605
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700606 void lowerArguments() override;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700607
Stefan Maksimovic6e033432016-11-09 17:31:51 -0800608 class Sandboxer {
609 Sandboxer() = delete;
610 Sandboxer(const Sandboxer &) = delete;
611 Sandboxer &operator=(const Sandboxer &) = delete;
612
613 public:
614 explicit Sandboxer(
615 TargetMIPS32 *Target,
616 InstBundleLock::Option BundleOption = InstBundleLock::Opt_None);
617 ~Sandboxer();
618
619 void addiu_sp(uint32_t StackOffset);
620 void lw(Variable *Dest, OperandMIPS32Mem *Mem);
621 void sw(Variable *Dest, OperandMIPS32Mem *Mem);
Stefan Maksimovic298d14e2017-01-11 05:58:27 -0800622 void ll(Variable *Dest, OperandMIPS32Mem *Mem);
623 void sc(Variable *Dest, OperandMIPS32Mem *Mem);
Stefan Maksimovic6e033432016-11-09 17:31:51 -0800624 void lwc1(Variable *Dest, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No);
625 void ldc1(Variable *Dest, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No);
626 void ret(Variable *RetAddr, Variable *RetValue);
627 void reset_sp(Variable *Src);
628 InstMIPS32Call *jal(Variable *ReturnReg, Operand *CallTarget);
629
630 private:
631 TargetMIPS32 *const Target;
632 const InstBundleLock::Option BundleOption;
633 std::unique_ptr<AutoBundle> Bundler;
634
635 void createAutoBundle();
636 };
637
638 const bool NeedSandboxing;
639
Sagar Thakur752e59f2016-07-21 06:12:09 -0700640 /// Make a pass through the SortedSpilledVariables and actually assign stack
641 /// slots. SpillAreaPaddingBytes takes into account stack alignment padding.
642 /// The SpillArea starts after that amount of padding. This matches the scheme
643 /// in getVarStackSlotParams, where there may be a separate multi-block global
644 /// var spill area and a local var spill area.
645 void assignVarStackSlots(VarList &SortedSpilledVariables,
646 size_t SpillAreaPaddingBytes,
647 size_t SpillAreaSizeBytes,
648 size_t GlobalsAndSubsequentPaddingSize);
649
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700650 /// Operand legalization helpers. To deal with address mode constraints,
651 /// the helpers will create a new Operand and emit instructions that
652 /// guarantee that the Operand kind is one of those indicated by the
653 /// LegalMask (a bitmask of allowed kinds). If the input Operand is known
654 /// to already meet the constraints, it may be simply returned as the result,
655 /// without creating any new instructions or operands.
656 enum OperandLegalization {
657 Legal_None = 0,
658 Legal_Reg = 1 << 0, // physical register, not stack location
659 Legal_Imm = 1 << 1,
660 Legal_Mem = 1 << 2,
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700661 Legal_Rematerializable = 1 << 3,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800662 Legal_Default = ~Legal_None
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700663 };
664 typedef uint32_t LegalMask;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800665 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800666 RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700667
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800668 Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700669
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800670 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700671
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800672 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
Reed Kotler953568f2016-02-17 05:37:01 -0800673
Sagar Thakur1a478b12016-04-25 08:39:19 -0700674 Variable *getZero() {
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -0800675 auto *Zero = makeReg(IceType_i32, RegMIPS32::Reg_ZERO);
676 Context.insert<InstFakeDef>(Zero);
677 return Zero;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700678 }
679
Reed Kotler953568f2016-02-17 05:37:01 -0800680 Variable *I32Reg(RegNumT RegNum = RegNumT()) {
681 return makeReg(IceType_i32, RegNum);
682 }
683
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700684 Variable *F32Reg(RegNumT RegNum = RegNumT()) {
685 return makeReg(IceType_f32, RegNum);
686 }
687
688 Variable *F64Reg(RegNumT RegNum = RegNumT()) {
689 return makeReg(IceType_f64, RegNum);
690 }
691
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700692 static Type stackSlotType();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800693 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700694
Sagar Thakur1afb4832016-06-16 15:30:24 -0700695 void unsetIfNonLeafFunc();
696
Sagar Thakura49fce02016-06-13 05:55:00 -0700697 // Iterates over the CFG and determines the maximum outgoing stack arguments
698 // bytes. This information is later used during addProlog() to pre-allocate
699 // the outargs area
700 void findMaxStackOutArgsSize();
701
Sagar Thakur5674c912016-07-14 14:50:37 -0700702 void postLowerLegalization();
703
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700704 void addProlog(CfgNode *Node) override;
705 void addEpilog(CfgNode *Node) override;
706
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700707 // Ensure that a 64-bit Variable has been split into 2 32-bit
708 // Variables, creating them if necessary. This is needed for all
709 // I64 operations.
710 void split64(Variable *Var);
711 Operand *loOperand(Operand *Operand);
712 Operand *hiOperand(Operand *Operand);
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700713 Operand *getOperandAtIndex(Operand *Operand, Type BaseType, uint32_t Index);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700714
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700715 void finishArgumentLowering(Variable *Arg, bool PartialOnStack,
716 Variable *FramePtr, size_t BasicFrameOffset,
717 size_t *InArgsSizeBytes);
Sagar Thakura49fce02016-06-13 05:55:00 -0700718
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800719 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700720
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700721 /// Helper class that understands the Calling Convention and register
722 /// assignments as per MIPS O32 abi.
723 class CallingConv {
724 CallingConv(const CallingConv &) = delete;
725 CallingConv &operator=(const CallingConv &) = delete;
726
727 public:
728 CallingConv();
729 ~CallingConv() = default;
730
731 /// argInReg returns true if there is a Register available for the requested
732 /// type, and false otherwise. If it returns true, Reg is set to the
733 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
734 /// be an I64 register pair.
735 bool argInReg(Type Ty, uint32_t ArgNo, RegNumT *Reg);
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700736 void discardReg(RegNumT Reg) { GPRegsUsed |= RegisterAliases[Reg]; }
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700737
738 private:
739 // argInGPR is used to find if any GPR register is available for argument of
740 // type Ty
741 bool argInGPR(Type Ty, RegNumT *Reg);
742 /// argInVFP is to floating-point/vector types what argInGPR is for integer
743 /// types.
744 bool argInVFP(Type Ty, RegNumT *Reg);
745 inline void discardNextGPRAndItsAliases(CfgVector<RegNumT> *Regs);
Mohit Bhakkadbbb5fa72016-06-29 06:51:08 -0700746 inline void alignGPR(CfgVector<RegNumT> *Regs);
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700747 void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
748 SmallBitVector GPRegsUsed;
749 CfgVector<RegNumT> GPRArgs;
750 CfgVector<RegNumT> I64Args;
751
752 void discardUnavailableVFPRegsAndTheirAliases(CfgVector<RegNumT> *Regs);
753 SmallBitVector VFPRegsUsed;
754 CfgVector<RegNumT> FP32Args;
755 CfgVector<RegNumT> FP64Args;
756 // UseFPRegs is a flag indicating if FP registers can be used
757 bool UseFPRegs = false;
758 };
759
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700760protected:
761 explicit TargetMIPS32(Cfg *Func);
762
763 void postLower() override;
764
Reed Kotler04bca5a2016-02-03 14:40:47 -0800765 void lowerAlloca(const InstAlloca *Instr) override;
766 void lowerArithmetic(const InstArithmetic *Instr) override;
767 void lowerInt64Arithmetic(const InstArithmetic *Instr, Variable *Dest,
Reed Kotler00e36042016-02-01 20:52:19 -0800768 Operand *Src0, Operand *Src1);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800769 void lowerAssign(const InstAssign *Instr) override;
770 void lowerBr(const InstBr *Instr) override;
Eric Holk67c7c412016-04-15 13:05:37 -0700771 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800772 void lowerCall(const InstCall *Instr) override;
773 void lowerCast(const InstCast *Instr) override;
774 void lowerExtractElement(const InstExtractElement *Instr) override;
775 void lowerFcmp(const InstFcmp *Instr) override;
776 void lowerIcmp(const InstIcmp *Instr) override;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700777 void lower64Icmp(const InstIcmp *Instr);
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800778 void createArithInst(Intrinsics::AtomicRMWOperation Operation, Variable *Dest,
779 Variable *Src0, Variable *Src1);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800780 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
781 void lowerInsertElement(const InstInsertElement *Instr) override;
782 void lowerLoad(const InstLoad *Instr) override;
783 void lowerPhi(const InstPhi *Instr) override;
784 void lowerRet(const InstRet *Instr) override;
785 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700786 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800787 void lowerStore(const InstStore *Instr) override;
788 void lowerSwitch(const InstSwitch *Instr) override;
789 void lowerUnreachable(const InstUnreachable *Instr) override;
Jaydeep Patil71f6c8d2017-02-10 06:45:40 -0800790 void lowerOther(const Inst *Instr) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700791 void prelowerPhis() override;
Sagar Thakur46832372016-10-16 07:20:44 -0700792 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
Srdjan Obucinab85cde12016-09-09 09:39:52 -0700793 void genTargetHelperCallFor(Inst *Instr) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700794 void doAddressOptLoad() override;
795 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700796 void randomlyInsertNop(float Probability,
797 RandomNumberGenerator &RNG) override;
798 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800799 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800800 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700801 uint64_t Salt) const override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700802
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700803 OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
804
Sagar Thakur5674c912016-07-14 14:50:37 -0700805 class PostLoweringLegalizer {
806 PostLoweringLegalizer() = delete;
807 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
808 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
809
810 public:
811 explicit PostLoweringLegalizer(TargetMIPS32 *Target)
812 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
813 Target->getFrameOrStackReg())) {}
814
Jaydeep Patilec929172016-10-16 07:13:38 -0700815 /// Legalizes Mem. if Mem.Base is a rematerializable variable,
816 /// Mem.Offset is fixed up.
817 OperandMIPS32Mem *legalizeMemOperand(OperandMIPS32Mem *Mem);
818
Sagar Thakur89be8872016-10-18 07:32:21 -0700819 /// Legalizes Immediate if larger value overflows range of 16 bits
820 Variable *legalizeImmediate(int32_t Imm);
821
Sagar Thakur5674c912016-07-14 14:50:37 -0700822 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
823 /// if its Source is a Rematerializable variable (this form is used in lieu
824 /// of lea, which is not available in MIPS.)
825 ///
826 /// Moves to memory become store instructions, and moves from memory, loads.
827 void legalizeMov(InstMIPS32Mov *Mov);
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -0800828 void legalizeMovFp(InstMIPS32MovFP64ToI64 *MovInstr);
Sagar Thakur5674c912016-07-14 14:50:37 -0700829
830 private:
831 /// Creates a new Base register centered around [Base, +/- Offset].
832 Variable *newBaseRegister(Variable *Base, int32_t Offset,
833 RegNumT ScratchRegNum);
834
835 TargetMIPS32 *const Target;
836 Variable *const StackOrFrameReg;
837 };
838
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700839 bool UsesFramePointer = false;
840 bool NeedsStackAlignment = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700841 bool MaybeLeafFunc = true;
842 bool PrologEmitsFixedAllocas = false;
Sagar Thakurc930d592016-07-12 04:06:44 -0700843 bool VariableAllocaUsed = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700844 uint32_t MaxOutArgsSizeBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700845 uint32_t TotalStackSizeBytes = 0;
Sagar Thakur46832372016-10-16 07:20:44 -0700846 uint32_t CurrentAllocaOffset = 0;
Sagar Thakur89be8872016-10-18 07:32:21 -0700847 uint32_t VariableAllocaAlignBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -0800848 static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
849 static SmallBitVector TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
850 static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
851 SmallBitVector RegsUsed;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700852 VarList PhysicalRegisters[IceType_NUM];
Sagar Thakura49fce02016-06-13 05:55:00 -0700853 VarList PreservedGPRs;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700854 static constexpr uint32_t CHAR_BITS = 8;
855 static constexpr uint32_t INT32_BITS = 32;
Sagar Thakura49fce02016-06-13 05:55:00 -0700856 size_t SpillAreaSizeBytes = 0;
Sagar Thakur1afb4832016-06-16 15:30:24 -0700857 size_t FixedAllocaSizeBytes = 0;
858 size_t FixedAllocaAlignBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700859 size_t PreservedRegsSizeBytes = 0;
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700860 Variable *ImplicitRet = nullptr; /// Implicit return
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700861
862private:
John Porto53611e22015-12-30 07:30:10 -0800863 ENABLE_MAKE_UNIQUE;
Sagar Thakur5cce7612016-05-24 06:25:50 -0700864
Jaydeep Patil47ef0be2016-09-13 06:09:48 -0700865 OperandMIPS32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
866 Operand *Base);
867
Sagar Thakur5cce7612016-05-24 06:25:50 -0700868 class ComputationTracker {
869 public:
870 ComputationTracker() = default;
871 ~ComputationTracker() = default;
872
873 void forgetProducers() { KnownComputations.clear(); }
874 void recordProducers(CfgNode *Node);
875
876 const Inst *getProducerOf(const Operand *Opnd) const {
877 auto *Var = llvm::dyn_cast<Variable>(Opnd);
878 if (Var == nullptr) {
879 return nullptr;
880 }
881
882 auto Iter = KnownComputations.find(Var->getIndex());
883 if (Iter == KnownComputations.end()) {
884 return nullptr;
885 }
886
887 return Iter->second.Instr;
888 }
889
890 void dump(const Cfg *Func) const {
891 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
892 return;
893 OstreamLocker L(Func->getContext());
894 Ostream &Str = Func->getContext()->getStrDump();
895 Str << "foldable producer:\n";
896 for (const auto &Computation : KnownComputations) {
897 Str << " ";
898 Computation.second.Instr->dump(Func);
899 Str << "\n";
900 }
901 Str << "\n";
902 }
903
904 private:
905 class ComputationEntry {
906 public:
907 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
908 Inst *const Instr;
909 // Boolean folding is disabled for variables whose live range is multi
910 // block. We conservatively initialize IsLiveOut to true, and set it to
911 // false once we find the end of the live range for the variable defined
912 // by this instruction. If liveness analysis is not performed (e.g., in
913 // Om1 mode) IsLiveOut will never be set to false, and folding will be
914 // disabled.
915 bool IsLiveOut = true;
916 int32_t NumUses = 0;
917 Type ComputationType;
918 };
919
920 // ComputationMap maps a Variable number to a payload identifying which
921 // instruction defined it.
922 using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
923 ComputationMap KnownComputations;
924 };
925
926 ComputationTracker Computations;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700927};
928
John Porto0f86d032015-06-15 07:44:27 -0700929class TargetDataMIPS32 final : public TargetDataLowering {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700930 TargetDataMIPS32() = delete;
931 TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
932 TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
933
934public:
Jan Voungfb792842015-06-11 15:27:50 -0700935 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
936 return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700937 }
938
John Porto8b1a7052015-06-17 13:20:08 -0700939 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700940 const std::string &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700941 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -0700942 void lowerJumpTables() override;
Jaydeep Patil3da9f652016-11-03 22:54:06 -0700943 void emitTargetRODataSections() override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700944
945protected:
946 explicit TargetDataMIPS32(GlobalContext *Ctx);
947
948private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700949 ~TargetDataMIPS32() override = default;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700950};
951
Jan Voungfb792842015-06-11 15:27:50 -0700952class TargetHeaderMIPS32 final : public TargetHeaderLowering {
953 TargetHeaderMIPS32() = delete;
954 TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
955 TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
956
957public:
958 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
959 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
960 }
961
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700962 void lower() override;
963
Jan Voungfb792842015-06-11 15:27:50 -0700964protected:
965 explicit TargetHeaderMIPS32(GlobalContext *Ctx);
966
967private:
968 ~TargetHeaderMIPS32() = default;
969};
970
Jaydeep Patil3da9f652016-11-03 22:54:06 -0700971// This structure (with some minor modifications) is copied from
972// llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h file.
973struct MipsABIFlagsSection {
974
975 // Version of the MIPS.abiflags section
976 enum AFL_VERSION {
977 AFL_VERSION_V0 = 0 // Version 0
978 };
979
980 // The level of the ISA: 1-5, 32, 64.
981 enum AFL_ISA_LEVEL {
982 AFL_ISA_LEVEL_NONE = 0,
983 AFL_ISA_LEVEL_MIPS32 = 32, // MIPS32
984 };
985
986 // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
987 enum AFL_ISA_REV {
988 AFL_ISA_REV_NONE = 0,
989 AFL_ISA_REV_R1 = 1, // R1
990 };
991
992 // Values for the xxx_size bytes of an ABI flags structure.
993 enum AFL_REG {
994 AFL_REG_NONE = 0x00, // No registers.
995 AFL_REG_32 = 0x01, // 32-bit registers.
996 AFL_REG_64 = 0x02, // 64-bit registers.
997 AFL_REG_128 = 0x03 // 128-bit registers.
998 };
999
1000 // Values for the fp_abi word of an ABI flags structure.
1001 enum AFL_FP_ABI {
1002 AFL_FP_ANY = 0,
1003 AFL_FP_DOUBLE = 1,
1004 AFL_FP_XX = 5,
1005 AFL_FP_64 = 6,
1006 AFL_FP_64A = 7
1007 };
1008
1009 // Values for the isa_ext word of an ABI flags structure.
1010 enum AFL_EXT {
1011 AFL_EXT_NONE = 0,
1012 AFL_EXT_XLR = 1, // RMI Xlr instruction.
1013 AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2.
1014 AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP.
1015 AFL_EXT_LOONGSON_3A = 4, // Loongson 3A.
1016 AFL_EXT_OCTEON = 5, // Cavium Networks Octeon.
1017 AFL_EXT_5900 = 6, // MIPS R5900 instruction.
1018 AFL_EXT_4650 = 7, // MIPS R4650 instruction.
1019 AFL_EXT_4010 = 8, // LSI R4010 instruction.
1020 AFL_EXT_4100 = 9, // NEC VR4100 instruction.
1021 AFL_EXT_3900 = 10, // Toshiba R3900 instruction.
1022 AFL_EXT_10000 = 11, // MIPS R10000 instruction.
1023 AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction.
1024 AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction.
1025 AFL_EXT_4120 = 14, // NEC VR4120 instruction.
1026 AFL_EXT_5400 = 15, // NEC VR5400 instruction.
1027 AFL_EXT_5500 = 16, // NEC VR5500 instruction.
1028 AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E.
1029 AFL_EXT_LOONGSON_2F = 18 // ST Microelectronics Loongson 2F.
1030 };
1031
1032 // Masks for the ases word of an ABI flags structure.
1033 enum AFL_ASE {
1034 AFL_ASE_NONE = 0x00000000,
1035 AFL_ASE_DSP = 0x00000001, // DSP ASE.
1036 AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE.
1037 AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme.
1038 AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE.
1039 AFL_ASE_MDMX = 0x00000010, // MDMX ASE.
1040 AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE.
1041 AFL_ASE_MT = 0x00000040, // MT ASE.
1042 AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE.
1043 AFL_ASE_VIRT = 0x00000100, // VZ ASE.
1044 AFL_ASE_MSA = 0x00000200, // MSA ASE.
1045 AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE.
1046 AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE.
1047 AFL_ASE_XPA = 0x00001000 // XPA ASE.
1048 };
1049
1050 enum AFL_FLAGS1 { AFL_FLAGS1_NONE = 0, AFL_FLAGS1_ODDSPREG = 1 };
1051
1052 enum AFL_FLAGS2 { AFL_FLAGS2_NONE = 0 };
1053
1054 uint16_t Version = AFL_VERSION_V0;
1055 uint8_t ISALevel = AFL_ISA_LEVEL_MIPS32;
1056 uint8_t ISARevision = AFL_ISA_REV_R1;
1057 uint8_t GPRSize = AFL_REG_32;
1058 uint8_t CPR1Size = AFL_REG_32;
1059 uint8_t CPR2Size = AFL_REG_NONE;
1060 uint8_t FPABI = AFL_FP_DOUBLE;
1061 uint32_t Extension = AFL_EXT_NONE;
1062 uint32_t ASE = AFL_ASE_NONE;
1063 uint32_t Flags1 = AFL_FLAGS1_ODDSPREG;
1064 uint32_t Flags2 = AFL_FLAGS2_NONE;
1065
1066 MipsABIFlagsSection() = default;
1067};
1068
John Porto4a566862016-01-04 09:33:41 -08001069} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07001070} // end of namespace Ice
1071
1072#endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H