blob: 5406087c555233ff8d74395801841ba4ad15b126 [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
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700115 bool shouldSplitToVariable64On32(Type Ty) const override {
116 return Ty == IceType_i64;
117 }
118
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700119 bool shouldSplitToVariableVecOn32(Type Ty) const override {
120 return isVectorType(Ty);
121 }
122
Andrew Scull87f80c12015-07-20 10:19:16 -0700123 // TODO(ascull): what is the best size of MIPS?
124 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700125 void emitJumpTable(const Cfg *Func,
126 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700127
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700128 void emitVariable(const Variable *Var) const override;
129
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700130 void emit(const ConstantInteger32 *C) const final {
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700131 if (!BuildDefs::dump())
132 return;
133 Ostream &Str = Ctx->getStrEmit();
134 Str << C->getValue();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700135 }
136 void emit(const ConstantInteger64 *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 }
140 void emit(const ConstantFloat *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700141 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700142 llvm::report_fatal_error("Not yet implemented");
143 }
144 void emit(const ConstantDouble *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700145 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700146 llvm::report_fatal_error("Not yet implemented");
147 }
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800148 void emit(const ConstantUndef *C) const final {
149 (void)C;
150 llvm::report_fatal_error("Not yet implemented");
151 }
152 void emit(const ConstantRelocatable *C) const final {
153 (void)C;
154 llvm::report_fatal_error("Not yet implemented");
155 }
Reed Kotler37af5b02015-11-05 17:07:19 -0800156
157 // The following are helpers that insert lowered MIPS32 instructions with
158 // minimal syntactic overhead, so that the lowering code can look as close to
159 // assembly as practical.
160 void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800161 Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800162 }
163
Reed Kotler00e36042016-02-01 20:52:19 -0800164 void _addu(Variable *Dest, Variable *Src0, Variable *Src1) {
165 Context.insert<InstMIPS32Addu>(Dest, Src0, Src1);
166 }
167
Reed Kotler37af5b02015-11-05 17:07:19 -0800168 void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800169 Context.insert<InstMIPS32And>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800170 }
171
Sagar Thakur38dcb592016-05-09 11:57:59 -0700172 void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
173 Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
174 }
175
Reed Kotler3fe4b572016-02-23 18:59:43 -0800176 void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
177
Sagar Thakur5cce7612016-05-24 06:25:50 -0700178 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
179 Operand *Src1, CondMIPS32::Cond Condition) {
180 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1,
181 Condition);
182 }
183
184 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
185 CondMIPS32::Cond Condition) {
186 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Condition);
187 }
188
Jaydeep Patil29823f12016-08-31 05:10:03 -0700189 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
190 Operand *Src1, const InstMIPS32Label *Label,
191 CondMIPS32::Cond Condition) {
192 Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1, Label,
193 Condition);
194 }
195
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700196 void _ret(Variable *RA, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800197 Context.insert<InstMIPS32Ret>(RA, Src0);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700198 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700199
Srdjan Obucina53d05682016-09-10 08:25:37 -0700200 void _abs_d(Variable *Dest, Variable *Src) {
201 Context.insert<InstMIPS32Abs_d>(Dest, Src);
202 }
203
204 void _abs_s(Variable *Dest, Variable *Src) {
205 Context.insert<InstMIPS32Abs_s>(Dest, Src);
206 }
207
Jaydeep Patil130aca72016-10-28 05:30:54 -0700208 void _addi(Variable *Dest, Variable *Src, uint32_t Imm) {
209 Context.insert<InstMIPS32Addi>(Dest, Src, Imm);
210 }
211
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700212 void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
213 Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
214 }
215
216 void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
217 Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
218 }
219
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700220 void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800221 Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700222 }
223
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -0700224 void _addiu(Variable *Dest, Variable *Src0, Operand *Src1, RelocOp Reloc) {
225 Context.insert<InstMIPS32Addiu>(Dest, Src0, Src1, Reloc);
226 }
227
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700228 void _c_eq_d(Variable *Src0, Variable *Src1) {
229 Context.insert<InstMIPS32C_eq_d>(Src0, Src1);
230 }
231
232 void _c_eq_s(Variable *Src0, Variable *Src1) {
233 Context.insert<InstMIPS32C_eq_s>(Src0, Src1);
234 }
235
236 void _c_ole_d(Variable *Src0, Variable *Src1) {
237 Context.insert<InstMIPS32C_ole_d>(Src0, Src1);
238 }
239
240 void _c_ole_s(Variable *Src0, Variable *Src1) {
241 Context.insert<InstMIPS32C_ole_s>(Src0, Src1);
242 }
243
244 void _c_olt_d(Variable *Src0, Variable *Src1) {
245 Context.insert<InstMIPS32C_olt_d>(Src0, Src1);
246 }
247
248 void _c_olt_s(Variable *Src0, Variable *Src1) {
249 Context.insert<InstMIPS32C_olt_s>(Src0, Src1);
250 }
251
252 void _c_ueq_d(Variable *Src0, Variable *Src1) {
253 Context.insert<InstMIPS32C_ueq_d>(Src0, Src1);
254 }
255
256 void _c_ueq_s(Variable *Src0, Variable *Src1) {
257 Context.insert<InstMIPS32C_ueq_s>(Src0, Src1);
258 }
259
260 void _c_ule_d(Variable *Src0, Variable *Src1) {
261 Context.insert<InstMIPS32C_ule_d>(Src0, Src1);
262 }
263
264 void _c_ule_s(Variable *Src0, Variable *Src1) {
265 Context.insert<InstMIPS32C_ule_s>(Src0, Src1);
266 }
267
268 void _c_ult_d(Variable *Src0, Variable *Src1) {
269 Context.insert<InstMIPS32C_ult_d>(Src0, Src1);
270 }
271
272 void _c_ult_s(Variable *Src0, Variable *Src1) {
273 Context.insert<InstMIPS32C_ult_s>(Src0, Src1);
274 }
275
276 void _c_un_d(Variable *Src0, Variable *Src1) {
277 Context.insert<InstMIPS32C_un_d>(Src0, Src1);
278 }
279
280 void _c_un_s(Variable *Src0, Variable *Src1) {
281 Context.insert<InstMIPS32C_un_s>(Src0, Src1);
282 }
283
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700284 void _clz(Variable *Dest, Variable *Src) {
285 Context.insert<InstMIPS32Clz>(Dest, Src);
286 }
287
Srdjan Obucina418135a2016-06-02 06:47:06 -0700288 void _cvt_d_l(Variable *Dest, Variable *Src) {
289 Context.insert<InstMIPS32Cvt_d_l>(Dest, Src);
290 }
291
292 void _cvt_d_s(Variable *Dest, Variable *Src) {
293 Context.insert<InstMIPS32Cvt_d_s>(Dest, Src);
294 }
295
296 void _cvt_d_w(Variable *Dest, Variable *Src) {
297 Context.insert<InstMIPS32Cvt_d_w>(Dest, Src);
298 }
299
300 void _cvt_s_d(Variable *Dest, Variable *Src) {
301 Context.insert<InstMIPS32Cvt_s_d>(Dest, Src);
302 }
303
304 void _cvt_s_l(Variable *Dest, Variable *Src) {
305 Context.insert<InstMIPS32Cvt_s_l>(Dest, Src);
306 }
307
308 void _cvt_s_w(Variable *Dest, Variable *Src) {
309 Context.insert<InstMIPS32Cvt_s_w>(Dest, Src);
310 }
311
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700312 void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
313 Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
314 }
315
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700316 void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
317 Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
318 }
319
320 void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
321 Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
322 }
323
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700324 void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
325 Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
326 }
327
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700328 void _ldc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
329 Context.insert<InstMIPS32Ldc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700330 }
331
Sagar Thakur633394c2016-06-25 08:34:10 -0700332 void _lw(Variable *Value, OperandMIPS32Mem *Mem) {
333 Context.insert<InstMIPS32Lw>(Value, Mem);
334 }
335
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700336 void _lwc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
337 Context.insert<InstMIPS32Lwc1>(Value, Mem, Reloc);
Srdjan Obucina418135a2016-06-02 06:47:06 -0700338 }
339
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700340 void _lui(Variable *Dest, Operand *Src, RelocOp Reloc = RO_No) {
341 Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700342 }
343
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700344 void _mfc1(Variable *Dest, Variable *Src) {
345 Context.insert<InstMIPS32Mfc1>(Dest, Src);
346 }
347
348 void _mfhi(Variable *Dest, Operand *Src) {
349 Context.insert<InstMIPS32Mfhi>(Dest, Src);
350 }
351
352 void _mflo(Variable *Dest, Operand *Src) {
353 Context.insert<InstMIPS32Mflo>(Dest, Src);
354 }
355
Sagar Thakurb001cc42016-10-11 23:36:01 -0700356 void _mov(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700357 assert(Dest != nullptr);
358 // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
359 if (llvm::isa<ConstantRelocatable>(Src0)) {
John Porto1d937a82015-12-17 06:19:34 -0800360 Context.insert<InstMIPS32La>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700361 } else {
Sagar Thakurb001cc42016-10-11 23:36:01 -0700362 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
363 if (Instr->getDestHi() != nullptr) {
364 // If DestHi is available, then Dest must be a Variable64On32. We add a
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700365 // fake-def for Instr.DestHi here.
366 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800367 Context.insert<InstFakeDef>(Instr->getDestHi());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700368 }
369 }
370 }
371
Stefan Maksimovicf8c99772016-11-02 05:59:06 -0700372 void _mov_redefined(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
373 if (llvm::isa<ConstantRelocatable>(Src0)) {
374 Context.insert<InstMIPS32La>(Dest, Src0);
375 } else {
376 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
377 Instr->setDestRedefined();
378 if (Instr->getDestHi() != nullptr) {
379 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
380 // fake-def for Instr.DestHi here.
381 assert(llvm::isa<Variable64On32>(Dest));
382 Context.insert<InstFakeDef>(Instr->getDestHi());
383 }
384 }
385 }
386
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700387 void _mov_d(Variable *Dest, Variable *Src) {
388 Context.insert<InstMIPS32Mov_d>(Dest, Src);
389 }
390
391 void _mov_s(Variable *Dest, Variable *Src) {
392 Context.insert<InstMIPS32Mov_s>(Dest, Src);
393 }
394
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700395 void _movf(Variable *Dest, Variable *Src0, Operand *FCC) {
396 Context.insert<InstMIPS32Movf>(Dest, Src0, FCC)->setDestRedefined();
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700397 }
398
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700399 void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700400 Context.insert<InstMIPS32Movn>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700401 }
402
403 void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700404 Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700405 }
406
407 void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700408 Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700409 }
410
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700411 void _movt(Variable *Dest, Variable *Src0, Operand *FCC) {
412 Context.insert<InstMIPS32Movt>(Dest, Src0, FCC)->setDestRedefined();
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700413 }
414
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700415 void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700416 Context.insert<InstMIPS32Movz>(Dest, Src0, Src1)->setDestRedefined();
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700417 }
418
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700419 void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700420 Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1)->setDestRedefined();
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800421 }
422
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700423 void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700424 Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1)->setDestRedefined();
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800425 }
426
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700427 void _mtc1(Variable *Dest, Variable *Src) {
428 Context.insert<InstMIPS32Mtc1>(Dest, Src);
429 }
430
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800431 void _mthi(Variable *Dest, Operand *Src) {
432 Context.insert<InstMIPS32Mthi>(Dest, Src);
433 }
434
435 void _mtlo(Variable *Dest, Operand *Src) {
436 Context.insert<InstMIPS32Mtlo>(Dest, Src);
437 }
438
Reed Kotler37af5b02015-11-05 17:07:19 -0800439 void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800440 Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800441 }
442
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700443 void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
444 Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
445 }
446
447 void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
448 Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
449 }
450
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800451 void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
452 Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
453 }
454
455 void _multu(Variable *Dest, Variable *Src0, Variable *Src1) {
456 Context.insert<InstMIPS32Multu>(Dest, Src0, Src1);
457 }
458
Srdjan Obucina8fbddc62016-09-15 17:26:40 -0700459 void _nop() { Context.insert<InstMIPS32Sll>(getZero(), getZero(), 0); }
460
Srdjan Obucinacadda792016-09-22 11:24:44 -0700461 void _nor(Variable *Dest, Variable *Src0, Variable *Src1) {
462 Context.insert<InstMIPS32Nor>(Dest, Src0, Src1);
463 }
464
465 void _not(Variable *Dest, Variable *Src0) {
466 Context.insert<InstMIPS32Nor>(Dest, Src0, getZero());
467 }
468
Reed Kotler37af5b02015-11-05 17:07:19 -0800469 void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800470 Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800471 }
472
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700473 void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800474 Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700475 }
476
Srdjan Obucina418135a2016-06-02 06:47:06 -0700477 void _sdc1(Variable *Value, OperandMIPS32Mem *Mem) {
478 Context.insert<InstMIPS32Sdc1>(Value, Mem);
479 }
480
Sagar Thakur38dcb592016-05-09 11:57:59 -0700481 void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
482 Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
483 }
484
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700485 void _sllv(Variable *Dest, Variable *Src0, Variable *Src1) {
486 Context.insert<InstMIPS32Sllv>(Dest, Src0, Src1);
487 }
488
Sagar Thakur1a478b12016-04-25 08:39:19 -0700489 void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
490 Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
491 }
492
493 void _slti(Variable *Dest, Variable *Src, uint32_t Imm) {
494 Context.insert<InstMIPS32Slti>(Dest, Src, Imm);
495 }
496
497 void _sltiu(Variable *Dest, Variable *Src, uint32_t Imm) {
498 Context.insert<InstMIPS32Sltiu>(Dest, Src, Imm);
Reed Kotler37af5b02015-11-05 17:07:19 -0800499 }
500
Reed Kotler00e36042016-02-01 20:52:19 -0800501 void _sltu(Variable *Dest, Variable *Src0, Variable *Src1) {
502 Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
503 }
504
Srdjan Obucina53d05682016-09-10 08:25:37 -0700505 void _sqrt_d(Variable *Dest, Variable *Src) {
506 Context.insert<InstMIPS32Sqrt_d>(Dest, Src);
507 }
508
509 void _sqrt_s(Variable *Dest, Variable *Src) {
510 Context.insert<InstMIPS32Sqrt_s>(Dest, Src);
511 }
512
Sagar Thakur38dcb592016-05-09 11:57:59 -0700513 void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
514 Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
515 }
516
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700517 void _srav(Variable *Dest, Variable *Src0, Variable *Src1) {
518 Context.insert<InstMIPS32Srav>(Dest, Src0, Src1);
519 }
520
521 void _srl(Variable *Dest, Variable *Src, uint32_t Imm) {
522 Context.insert<InstMIPS32Srl>(Dest, Src, Imm);
523 }
524
525 void _srlv(Variable *Dest, Variable *Src0, Variable *Src1) {
526 Context.insert<InstMIPS32Srlv>(Dest, Src0, Src1);
527 }
528
Sagar Thakur1a478b12016-04-25 08:39:19 -0700529 void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
530 Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
531 }
532
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700533 void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
534 Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
535 }
536
537 void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
538 Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
539 }
540
Reed Kotler00e36042016-02-01 20:52:19 -0800541 void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
542 Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
543 }
544
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700545 void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
546 Context.insert<InstMIPS32Sw>(Value, Mem);
547 }
548
Srdjan Obucina418135a2016-06-02 06:47:06 -0700549 void _swc1(Variable *Value, OperandMIPS32Mem *Mem) {
550 Context.insert<InstMIPS32Swc1>(Value, Mem);
551 }
552
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700553 void _teq(Variable *Src0, Variable *Src1, uint32_t TrapCode) {
554 Context.insert<InstMIPS32Teq>(Src0, Src1, TrapCode);
555 }
556
Srdjan Obucina418135a2016-06-02 06:47:06 -0700557 void _trunc_l_d(Variable *Dest, Variable *Src) {
558 Context.insert<InstMIPS32Trunc_l_d>(Dest, Src);
559 }
560
561 void _trunc_l_s(Variable *Dest, Variable *Src) {
562 Context.insert<InstMIPS32Trunc_l_s>(Dest, Src);
563 }
564
565 void _trunc_w_d(Variable *Dest, Variable *Src) {
566 Context.insert<InstMIPS32Trunc_w_d>(Dest, Src);
567 }
568
569 void _trunc_w_s(Variable *Dest, Variable *Src) {
570 Context.insert<InstMIPS32Trunc_w_s>(Dest, Src);
571 }
572
Reed Kotler37af5b02015-11-05 17:07:19 -0800573 void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800574 Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800575 }
576
Sagar Thakur1a478b12016-04-25 08:39:19 -0700577 void _xori(Variable *Dest, Variable *Src, uint32_t Imm) {
578 Context.insert<InstMIPS32Xori>(Dest, Src, Imm);
579 }
580
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700581 void lowerArguments() override;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700582
Sagar Thakur752e59f2016-07-21 06:12:09 -0700583 /// Make a pass through the SortedSpilledVariables and actually assign stack
584 /// slots. SpillAreaPaddingBytes takes into account stack alignment padding.
585 /// The SpillArea starts after that amount of padding. This matches the scheme
586 /// in getVarStackSlotParams, where there may be a separate multi-block global
587 /// var spill area and a local var spill area.
588 void assignVarStackSlots(VarList &SortedSpilledVariables,
589 size_t SpillAreaPaddingBytes,
590 size_t SpillAreaSizeBytes,
591 size_t GlobalsAndSubsequentPaddingSize);
592
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700593 /// Operand legalization helpers. To deal with address mode constraints,
594 /// the helpers will create a new Operand and emit instructions that
595 /// guarantee that the Operand kind is one of those indicated by the
596 /// LegalMask (a bitmask of allowed kinds). If the input Operand is known
597 /// to already meet the constraints, it may be simply returned as the result,
598 /// without creating any new instructions or operands.
599 enum OperandLegalization {
600 Legal_None = 0,
601 Legal_Reg = 1 << 0, // physical register, not stack location
602 Legal_Imm = 1 << 1,
603 Legal_Mem = 1 << 2,
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700604 Legal_Rematerializable = 1 << 3,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800605 Legal_Default = ~Legal_None
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700606 };
607 typedef uint32_t LegalMask;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800608 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800609 RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700610
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800611 Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700612
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800613 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700614
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800615 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
Reed Kotler953568f2016-02-17 05:37:01 -0800616
Sagar Thakur1a478b12016-04-25 08:39:19 -0700617 Variable *getZero() {
618 return getPhysicalRegister(RegMIPS32::Reg_ZERO, IceType_i32);
619 }
620
Reed Kotler953568f2016-02-17 05:37:01 -0800621 Variable *I32Reg(RegNumT RegNum = RegNumT()) {
622 return makeReg(IceType_i32, RegNum);
623 }
624
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700625 Variable *F32Reg(RegNumT RegNum = RegNumT()) {
626 return makeReg(IceType_f32, RegNum);
627 }
628
629 Variable *F64Reg(RegNumT RegNum = RegNumT()) {
630 return makeReg(IceType_f64, RegNum);
631 }
632
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700633 static Type stackSlotType();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800634 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700635
Sagar Thakur1afb4832016-06-16 15:30:24 -0700636 void unsetIfNonLeafFunc();
637
Sagar Thakura49fce02016-06-13 05:55:00 -0700638 // Iterates over the CFG and determines the maximum outgoing stack arguments
639 // bytes. This information is later used during addProlog() to pre-allocate
640 // the outargs area
641 void findMaxStackOutArgsSize();
642
Sagar Thakur5674c912016-07-14 14:50:37 -0700643 void postLowerLegalization();
644
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700645 void addProlog(CfgNode *Node) override;
646 void addEpilog(CfgNode *Node) override;
647
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700648 // Ensure that a 64-bit Variable has been split into 2 32-bit
649 // Variables, creating them if necessary. This is needed for all
650 // I64 operations.
651 void split64(Variable *Var);
652 Operand *loOperand(Operand *Operand);
653 Operand *hiOperand(Operand *Operand);
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700654 Operand *getOperandAtIndex(Operand *Operand, Type BaseType, uint32_t Index);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700655
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700656 void finishArgumentLowering(Variable *Arg, bool PartialOnStack,
657 Variable *FramePtr, size_t BasicFrameOffset,
658 size_t *InArgsSizeBytes);
Sagar Thakura49fce02016-06-13 05:55:00 -0700659
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800660 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700661
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700662 /// Helper class that understands the Calling Convention and register
663 /// assignments as per MIPS O32 abi.
664 class CallingConv {
665 CallingConv(const CallingConv &) = delete;
666 CallingConv &operator=(const CallingConv &) = delete;
667
668 public:
669 CallingConv();
670 ~CallingConv() = default;
671
672 /// argInReg returns true if there is a Register available for the requested
673 /// type, and false otherwise. If it returns true, Reg is set to the
674 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
675 /// be an I64 register pair.
676 bool argInReg(Type Ty, uint32_t ArgNo, RegNumT *Reg);
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700677 void discardReg(RegNumT Reg) { GPRegsUsed |= RegisterAliases[Reg]; }
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700678
679 private:
680 // argInGPR is used to find if any GPR register is available for argument of
681 // type Ty
682 bool argInGPR(Type Ty, RegNumT *Reg);
683 /// argInVFP is to floating-point/vector types what argInGPR is for integer
684 /// types.
685 bool argInVFP(Type Ty, RegNumT *Reg);
686 inline void discardNextGPRAndItsAliases(CfgVector<RegNumT> *Regs);
Mohit Bhakkadbbb5fa72016-06-29 06:51:08 -0700687 inline void alignGPR(CfgVector<RegNumT> *Regs);
Mohit Bhakkadf90118a2016-06-13 00:28:13 -0700688 void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
689 SmallBitVector GPRegsUsed;
690 CfgVector<RegNumT> GPRArgs;
691 CfgVector<RegNumT> I64Args;
692
693 void discardUnavailableVFPRegsAndTheirAliases(CfgVector<RegNumT> *Regs);
694 SmallBitVector VFPRegsUsed;
695 CfgVector<RegNumT> FP32Args;
696 CfgVector<RegNumT> FP64Args;
697 // UseFPRegs is a flag indicating if FP registers can be used
698 bool UseFPRegs = false;
699 };
700
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700701protected:
702 explicit TargetMIPS32(Cfg *Func);
703
704 void postLower() override;
705
Reed Kotler04bca5a2016-02-03 14:40:47 -0800706 void lowerAlloca(const InstAlloca *Instr) override;
707 void lowerArithmetic(const InstArithmetic *Instr) override;
708 void lowerInt64Arithmetic(const InstArithmetic *Instr, Variable *Dest,
Reed Kotler00e36042016-02-01 20:52:19 -0800709 Operand *Src0, Operand *Src1);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800710 void lowerAssign(const InstAssign *Instr) override;
711 void lowerBr(const InstBr *Instr) override;
Eric Holk67c7c412016-04-15 13:05:37 -0700712 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800713 void lowerCall(const InstCall *Instr) override;
714 void lowerCast(const InstCast *Instr) override;
715 void lowerExtractElement(const InstExtractElement *Instr) override;
716 void lowerFcmp(const InstFcmp *Instr) override;
717 void lowerIcmp(const InstIcmp *Instr) override;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700718 void lower64Icmp(const InstIcmp *Instr);
Reed Kotler04bca5a2016-02-03 14:40:47 -0800719 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
720 void lowerInsertElement(const InstInsertElement *Instr) override;
721 void lowerLoad(const InstLoad *Instr) override;
722 void lowerPhi(const InstPhi *Instr) override;
723 void lowerRet(const InstRet *Instr) override;
724 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700725 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Reed Kotler04bca5a2016-02-03 14:40:47 -0800726 void lowerStore(const InstStore *Instr) override;
727 void lowerSwitch(const InstSwitch *Instr) override;
728 void lowerUnreachable(const InstUnreachable *Instr) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700729 void prelowerPhis() override;
Sagar Thakur46832372016-10-16 07:20:44 -0700730 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
Srdjan Obucinab85cde12016-09-09 09:39:52 -0700731 void genTargetHelperCallFor(Inst *Instr) override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700732 void doAddressOptLoad() override;
733 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700734 void randomlyInsertNop(float Probability,
735 RandomNumberGenerator &RNG) override;
736 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800737 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800738 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700739 uint64_t Salt) const override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700740
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700741 OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
742
Sagar Thakur5674c912016-07-14 14:50:37 -0700743 class PostLoweringLegalizer {
744 PostLoweringLegalizer() = delete;
745 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
746 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
747
748 public:
749 explicit PostLoweringLegalizer(TargetMIPS32 *Target)
750 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
751 Target->getFrameOrStackReg())) {}
752
Jaydeep Patilec929172016-10-16 07:13:38 -0700753 /// Legalizes Mem. if Mem.Base is a rematerializable variable,
754 /// Mem.Offset is fixed up.
755 OperandMIPS32Mem *legalizeMemOperand(OperandMIPS32Mem *Mem);
756
Sagar Thakur89be8872016-10-18 07:32:21 -0700757 /// Legalizes Immediate if larger value overflows range of 16 bits
758 Variable *legalizeImmediate(int32_t Imm);
759
Sagar Thakur5674c912016-07-14 14:50:37 -0700760 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
761 /// if its Source is a Rematerializable variable (this form is used in lieu
762 /// of lea, which is not available in MIPS.)
763 ///
764 /// Moves to memory become store instructions, and moves from memory, loads.
765 void legalizeMov(InstMIPS32Mov *Mov);
766
767 private:
768 /// Creates a new Base register centered around [Base, +/- Offset].
769 Variable *newBaseRegister(Variable *Base, int32_t Offset,
770 RegNumT ScratchRegNum);
771
772 TargetMIPS32 *const Target;
773 Variable *const StackOrFrameReg;
774 };
775
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700776 bool UsesFramePointer = false;
777 bool NeedsStackAlignment = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700778 bool MaybeLeafFunc = true;
779 bool PrologEmitsFixedAllocas = false;
Sagar Thakurc930d592016-07-12 04:06:44 -0700780 bool VariableAllocaUsed = false;
Sagar Thakura49fce02016-06-13 05:55:00 -0700781 uint32_t MaxOutArgsSizeBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700782 uint32_t TotalStackSizeBytes = 0;
Sagar Thakur46832372016-10-16 07:20:44 -0700783 uint32_t CurrentAllocaOffset = 0;
Sagar Thakur89be8872016-10-18 07:32:21 -0700784 uint32_t VariableAllocaAlignBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -0800785 static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
786 static SmallBitVector TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
787 static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
788 SmallBitVector RegsUsed;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700789 VarList PhysicalRegisters[IceType_NUM];
Sagar Thakura49fce02016-06-13 05:55:00 -0700790 VarList PreservedGPRs;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700791 static constexpr uint32_t CHAR_BITS = 8;
792 static constexpr uint32_t INT32_BITS = 32;
Sagar Thakura49fce02016-06-13 05:55:00 -0700793 size_t SpillAreaSizeBytes = 0;
Sagar Thakur1afb4832016-06-16 15:30:24 -0700794 size_t FixedAllocaSizeBytes = 0;
795 size_t FixedAllocaAlignBytes = 0;
Sagar Thakur633394c2016-06-25 08:34:10 -0700796 size_t PreservedRegsSizeBytes = 0;
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700797 Variable *ImplicitRet = nullptr; /// Implicit return
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700798
799private:
John Porto53611e22015-12-30 07:30:10 -0800800 ENABLE_MAKE_UNIQUE;
Sagar Thakur5cce7612016-05-24 06:25:50 -0700801
Jaydeep Patil47ef0be2016-09-13 06:09:48 -0700802 OperandMIPS32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
803 Operand *Base);
804
Sagar Thakur5cce7612016-05-24 06:25:50 -0700805 class ComputationTracker {
806 public:
807 ComputationTracker() = default;
808 ~ComputationTracker() = default;
809
810 void forgetProducers() { KnownComputations.clear(); }
811 void recordProducers(CfgNode *Node);
812
813 const Inst *getProducerOf(const Operand *Opnd) const {
814 auto *Var = llvm::dyn_cast<Variable>(Opnd);
815 if (Var == nullptr) {
816 return nullptr;
817 }
818
819 auto Iter = KnownComputations.find(Var->getIndex());
820 if (Iter == KnownComputations.end()) {
821 return nullptr;
822 }
823
824 return Iter->second.Instr;
825 }
826
827 void dump(const Cfg *Func) const {
828 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
829 return;
830 OstreamLocker L(Func->getContext());
831 Ostream &Str = Func->getContext()->getStrDump();
832 Str << "foldable producer:\n";
833 for (const auto &Computation : KnownComputations) {
834 Str << " ";
835 Computation.second.Instr->dump(Func);
836 Str << "\n";
837 }
838 Str << "\n";
839 }
840
841 private:
842 class ComputationEntry {
843 public:
844 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
845 Inst *const Instr;
846 // Boolean folding is disabled for variables whose live range is multi
847 // block. We conservatively initialize IsLiveOut to true, and set it to
848 // false once we find the end of the live range for the variable defined
849 // by this instruction. If liveness analysis is not performed (e.g., in
850 // Om1 mode) IsLiveOut will never be set to false, and folding will be
851 // disabled.
852 bool IsLiveOut = true;
853 int32_t NumUses = 0;
854 Type ComputationType;
855 };
856
857 // ComputationMap maps a Variable number to a payload identifying which
858 // instruction defined it.
859 using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
860 ComputationMap KnownComputations;
861 };
862
863 ComputationTracker Computations;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700864};
865
John Porto0f86d032015-06-15 07:44:27 -0700866class TargetDataMIPS32 final : public TargetDataLowering {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700867 TargetDataMIPS32() = delete;
868 TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
869 TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
870
871public:
Jan Voungfb792842015-06-11 15:27:50 -0700872 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
873 return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700874 }
875
John Porto8b1a7052015-06-17 13:20:08 -0700876 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700877 const std::string &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700878 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -0700879 void lowerJumpTables() override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700880
881protected:
882 explicit TargetDataMIPS32(GlobalContext *Ctx);
883
884private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700885 ~TargetDataMIPS32() override = default;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700886};
887
Jan Voungfb792842015-06-11 15:27:50 -0700888class TargetHeaderMIPS32 final : public TargetHeaderLowering {
889 TargetHeaderMIPS32() = delete;
890 TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
891 TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
892
893public:
894 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
895 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
896 }
897
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700898 void lower() override;
899
Jan Voungfb792842015-06-11 15:27:50 -0700900protected:
901 explicit TargetHeaderMIPS32(GlobalContext *Ctx);
902
903private:
904 ~TargetHeaderMIPS32() = default;
905};
906
John Porto4a566862016-01-04 09:33:41 -0800907} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700908} // end of namespace Ice
909
910#endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H