OLD | NEW |
1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// | 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// This file implements the TargetLoweringMIPS32 class, which consists almost | 11 /// This file implements the TargetLoweringMIPS32 class, which consists almost |
12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
13 /// | 13 /// |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #include "IceTargetLoweringMIPS32.h" | 16 #include "IceTargetLoweringMIPS32.h" |
17 | 17 |
18 #include "IceCfg.h" | 18 #include "IceCfg.h" |
19 #include "IceCfgNode.h" | 19 #include "IceCfgNode.h" |
20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
21 #include "IceDefs.h" | 21 #include "IceDefs.h" |
22 #include "IceELFObjectWriter.h" | 22 #include "IceELFObjectWriter.h" |
23 #include "IceGlobalInits.h" | 23 #include "IceGlobalInits.h" |
24 #include "IceInstMIPS32.h" | 24 #include "IceInstMIPS32.h" |
25 #include "IceLiveness.h" | 25 #include "IceLiveness.h" |
26 #include "IceOperand.h" | 26 #include "IceOperand.h" |
| 27 #include "IcePhiLoweringImpl.h" |
27 #include "IceRegistersMIPS32.h" | 28 #include "IceRegistersMIPS32.h" |
28 #include "IceTargetLoweringMIPS32.def" | 29 #include "IceTargetLoweringMIPS32.def" |
29 #include "IceUtils.h" | 30 #include "IceUtils.h" |
30 #include "llvm/Support/MathExtras.h" | 31 #include "llvm/Support/MathExtras.h" |
31 | 32 |
32 namespace Ice { | 33 namespace Ice { |
33 | 34 |
| 35 using llvm::isInt; |
| 36 |
| 37 namespace { |
| 38 |
| 39 // The maximum number of arguments to pass in GPR registers. |
| 40 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; |
| 41 |
| 42 } // end of anonymous namespace |
| 43 |
34 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) { | 44 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) { |
35 // TODO: Don't initialize IntegerRegisters and friends every time. Instead, | 45 // TODO: Don't initialize IntegerRegisters and friends every time. Instead, |
36 // initialize in some sort of static initializer for the class. | 46 // initialize in some sort of static initializer for the class. |
| 47 |
37 llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); | 48 llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); |
38 llvm::SmallBitVector FloatRegisters(RegMIPS32::Reg_NUM); | 49 llvm::SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); |
| 50 llvm::SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); |
| 51 llvm::SmallBitVector Float64Registers(RegMIPS32::Reg_NUM); |
39 llvm::SmallBitVector VectorRegisters(RegMIPS32::Reg_NUM); | 52 llvm::SmallBitVector VectorRegisters(RegMIPS32::Reg_NUM); |
40 llvm::SmallBitVector InvalidRegisters(RegMIPS32::Reg_NUM); | 53 llvm::SmallBitVector InvalidRegisters(RegMIPS32::Reg_NUM); |
41 ScratchRegs.resize(RegMIPS32::Reg_NUM); | 54 ScratchRegs.resize(RegMIPS32::Reg_NUM); |
42 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 55 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
43 isFP) \ | 56 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
44 IntegerRegisters[RegMIPS32::val] = isInt; \ | 57 IntegerRegisters[RegMIPS32::val] = isInt; \ |
45 FloatRegisters[RegMIPS32::val] = isFP; \ | 58 I64PairRegisters[RegMIPS32::val] = isI64Pair; \ |
46 VectorRegisters[RegMIPS32::val] = isFP; \ | 59 Float32Registers[RegMIPS32::val] = isFP32; \ |
| 60 Float64Registers[RegMIPS32::val] = isFP64; \ |
| 61 VectorRegisters[RegMIPS32::val] = isVec128; \ |
47 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 62 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
48 RegisterAliases[RegMIPS32::val].set(RegMIPS32::val); \ | 63 for (SizeT RegAlias : alias_init) { \ |
| 64 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ |
| 65 "Duplicate alias for " #val); \ |
| 66 RegisterAliases[RegMIPS32::val].set(RegAlias); \ |
| 67 } \ |
| 68 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
| 69 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); \ |
49 ScratchRegs[RegMIPS32::val] = scratch; | 70 ScratchRegs[RegMIPS32::val] = scratch; |
50 REGMIPS32_TABLE; | 71 REGMIPS32_TABLE; |
51 #undef X | 72 #undef X |
52 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 73 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
53 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 74 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
54 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 75 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
55 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 76 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
56 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 77 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
57 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 78 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
58 TypeToRegisterSet[IceType_f32] = FloatRegisters; | 79 TypeToRegisterSet[IceType_f32] = Float32Registers; |
59 TypeToRegisterSet[IceType_f64] = FloatRegisters; | 80 TypeToRegisterSet[IceType_f64] = Float64Registers; |
60 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 81 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
61 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 82 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
62 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 83 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
63 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 84 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
64 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 85 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
65 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 86 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
66 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 87 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
67 } | 88 } |
68 | 89 |
69 void TargetMIPS32::translateO2() { | 90 void TargetMIPS32::translateO2() { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 (void)NextNode; | 227 (void)NextNode; |
207 UnimplementedError(Func->getContext()->getFlags()); | 228 UnimplementedError(Func->getContext()->getFlags()); |
208 return false; | 229 return false; |
209 } | 230 } |
210 | 231 |
211 IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const { | 232 IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const { |
212 assert(RegNum < RegMIPS32::Reg_NUM); | 233 assert(RegNum < RegMIPS32::Reg_NUM); |
213 (void)Ty; | 234 (void)Ty; |
214 static const char *RegNames[] = { | 235 static const char *RegNames[] = { |
215 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 236 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
216 isFP) \ | 237 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
217 name, | 238 name, |
218 REGMIPS32_TABLE | 239 REGMIPS32_TABLE |
219 #undef X | 240 #undef X |
220 }; | 241 }; |
221 return RegNames[RegNum]; | 242 return RegNames[RegNum]; |
222 } | 243 } |
223 | 244 |
224 Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 245 Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
225 if (Ty == IceType_void) | 246 if (Ty == IceType_void) |
226 Ty = IceType_i32; | 247 Ty = IceType_i32; |
(...skipping 14 matching lines...) Expand all Loading... |
241 } | 262 } |
242 return Reg; | 263 return Reg; |
243 } | 264 } |
244 | 265 |
245 void TargetMIPS32::emitJumpTable(const Cfg *Func, | 266 void TargetMIPS32::emitJumpTable(const Cfg *Func, |
246 const InstJumpTable *JumpTable) const { | 267 const InstJumpTable *JumpTable) const { |
247 (void)JumpTable; | 268 (void)JumpTable; |
248 UnimplementedError(Func->getContext()->getFlags()); | 269 UnimplementedError(Func->getContext()->getFlags()); |
249 } | 270 } |
250 | 271 |
| 272 /// Provide a trivial wrapper to legalize() for this common usage. |
| 273 Variable *TargetMIPS32::legalizeToReg(Operand *From, int32_t RegNum) { |
| 274 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 275 } |
| 276 |
| 277 /// Legalize undef values to concrete values. |
| 278 Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) { |
| 279 (void)RegNum; |
| 280 Type Ty = From->getType(); |
| 281 if (llvm::isa<ConstantUndef>(From)) { |
| 282 // Lower undefs to zero. Another option is to lower undefs to an |
| 283 // uninitialized register; however, using an uninitialized register |
| 284 // results in less predictable code. |
| 285 // |
| 286 // If in the future the implementation is changed to lower undef |
| 287 // values to uninitialized registers, a FakeDef will be needed: |
| 288 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 289 // This is in order to ensure that the live range of Reg is not |
| 290 // overestimated. If the constant being lowered is a 64 bit value, |
| 291 // then the result should be split and the lo and hi components will |
| 292 // need to go in uninitialized registers. |
| 293 if (isVectorType(Ty)) |
| 294 UnimplementedError(Func->getContext()->getFlags()); |
| 295 return Ctx->getConstantZero(Ty); |
| 296 } |
| 297 return From; |
| 298 } |
| 299 |
| 300 Variable *TargetMIPS32::makeReg(Type Type, int32_t RegNum) { |
| 301 // There aren't any 64-bit integer registers for Mips32. |
| 302 assert(Type != IceType_i64); |
| 303 Variable *Reg = Func->makeVariable(Type); |
| 304 if (RegNum == Variable::NoRegister) |
| 305 Reg->setMustHaveReg(); |
| 306 else |
| 307 Reg->setRegNum(RegNum); |
| 308 return Reg; |
| 309 } |
| 310 |
251 void TargetMIPS32::emitVariable(const Variable *Var) const { | 311 void TargetMIPS32::emitVariable(const Variable *Var) const { |
252 if (!BuildDefs::dump()) | 312 if (!BuildDefs::dump()) |
253 return; | 313 return; |
254 Ostream &Str = Ctx->getStrEmit(); | 314 Ostream &Str = Ctx->getStrEmit(); |
255 (void)Var; | 315 const Type FrameSPTy = IceType_i32; |
256 (void)Str; | 316 if (Var->hasReg()) { |
| 317 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); |
| 318 return; |
| 319 } else { |
| 320 int32_t Offset = Var->getStackOffset(); |
| 321 Str << Offset; |
| 322 Str << "(" << getRegName(getFrameOrStackReg(), FrameSPTy); |
| 323 Str << ")"; |
| 324 } |
257 UnimplementedError(Func->getContext()->getFlags()); | 325 UnimplementedError(Func->getContext()->getFlags()); |
258 } | 326 } |
259 | 327 |
260 void TargetMIPS32::lowerArguments() { | 328 void TargetMIPS32::lowerArguments() { |
261 VarList &Args = Func->getArgs(); | 329 VarList &Args = Func->getArgs(); |
262 if (Args.size() > 0) | 330 // We are only handling integer registers for now. The Mips o32 ABI is |
263 UnimplementedError(Func->getContext()->getFlags()); | 331 // somewhat complex but will be implemented in its totality through follow |
| 332 // on patches. |
| 333 // |
| 334 unsigned NumGPRRegsUsed = 0; |
| 335 // For each register argument, replace Arg in the argument list with the |
| 336 // home register. Then generate an instruction in the prolog to copy the |
| 337 // home register to the assigned location of Arg. |
| 338 Context.init(Func->getEntryNode()); |
| 339 Context.setInsertPoint(Context.getCur()); |
| 340 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 341 Variable *Arg = Args[I]; |
| 342 Type Ty = Arg->getType(); |
| 343 // TODO(rkotler): handle float/vector types. |
| 344 if (isVectorType(Ty)) { |
| 345 UnimplementedError(Func->getContext()->getFlags()); |
| 346 continue; |
| 347 } |
| 348 if (isFloatingType(Ty)) { |
| 349 UnimplementedError(Func->getContext()->getFlags()); |
| 350 continue; |
| 351 } |
| 352 if (Ty == IceType_i64) { |
| 353 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) |
| 354 continue; |
| 355 int32_t RegLo = RegMIPS32::Reg_A0 + NumGPRRegsUsed; |
| 356 int32_t RegHi = RegLo + 1; |
| 357 ++NumGPRRegsUsed; |
| 358 // Always start i64 registers at an even register, so this may end |
| 359 // up padding away a register. |
| 360 if (RegLo % 2 != 0) { |
| 361 ++RegLo; |
| 362 ++NumGPRRegsUsed; |
| 363 } |
| 364 // If this leaves us without room to consume another register, |
| 365 // leave any previously speculatively consumed registers as consumed. |
| 366 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) |
| 367 continue; |
| 368 // RegHi = RegMIPS32::Reg_A0 + NumGPRRegsUsed; |
| 369 ++NumGPRRegsUsed; |
| 370 Variable *RegisterArg = Func->makeVariable(Ty); |
| 371 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); |
| 372 if (BuildDefs::dump()) |
| 373 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 374 RegisterArg64On32->initHiLo(Func); |
| 375 RegisterArg64On32->setIsArg(); |
| 376 RegisterArg64On32->getLo()->setRegNum(RegLo); |
| 377 RegisterArg64On32->getHi()->setRegNum(RegHi); |
| 378 Arg->setIsArg(false); |
| 379 Args[I] = RegisterArg64On32; |
| 380 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 381 continue; |
| 382 } else { |
| 383 assert(Ty == IceType_i32); |
| 384 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) |
| 385 continue; |
| 386 int32_t RegNum = RegMIPS32::Reg_A0 + NumGPRRegsUsed; |
| 387 ++NumGPRRegsUsed; |
| 388 Variable *RegisterArg = Func->makeVariable(Ty); |
| 389 if (BuildDefs::dump()) { |
| 390 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 391 } |
| 392 RegisterArg->setRegNum(RegNum); |
| 393 RegisterArg->setIsArg(); |
| 394 Arg->setIsArg(false); |
| 395 Args[I] = RegisterArg; |
| 396 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 397 } |
| 398 } |
264 } | 399 } |
265 | 400 |
266 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | 401 Type TargetMIPS32::stackSlotType() { return IceType_i32; } |
267 | 402 |
268 void TargetMIPS32::addProlog(CfgNode *Node) { | 403 void TargetMIPS32::addProlog(CfgNode *Node) { |
269 (void)Node; | 404 (void)Node; |
| 405 return; |
270 UnimplementedError(Func->getContext()->getFlags()); | 406 UnimplementedError(Func->getContext()->getFlags()); |
271 } | 407 } |
272 | 408 |
273 void TargetMIPS32::addEpilog(CfgNode *Node) { | 409 void TargetMIPS32::addEpilog(CfgNode *Node) { |
274 (void)Node; | 410 (void)Node; |
275 UnimplementedError(Func->getContext()->getFlags()); | 411 return; |
| 412 UnimplementedError(Func->getContext()->getFlags()); |
| 413 } |
| 414 |
| 415 Operand *TargetMIPS32::loOperand(Operand *Operand) { |
| 416 assert(Operand->getType() == IceType_i64); |
| 417 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| 418 return Var64On32->getLo(); |
| 419 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 420 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 421 } |
| 422 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { |
| 423 // Conservatively disallow memory operands with side-effects (pre/post |
| 424 // increment) in case of duplication. |
| 425 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); |
| 426 return OperandMIPS32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 427 Mem->getOffset(), Mem->getAddrMode()); |
| 428 } |
| 429 llvm_unreachable("Unsupported operand type"); |
| 430 return nullptr; |
| 431 } |
| 432 |
| 433 Operand *TargetMIPS32::hiOperand(Operand *Operand) { |
| 434 assert(Operand->getType() == IceType_i64); |
| 435 if (Operand->getType() != IceType_i64) |
| 436 return Operand; |
| 437 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| 438 return Var64On32->getHi(); |
| 439 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 440 return Ctx->getConstantInt32( |
| 441 static_cast<uint32_t>(Const->getValue() >> 32)); |
| 442 } |
| 443 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { |
| 444 // Conservatively disallow memory operands with side-effects |
| 445 // in case of duplication. |
| 446 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); |
| 447 const Type SplitType = IceType_i32; |
| 448 Variable *Base = Mem->getBase(); |
| 449 ConstantInteger32 *Offset = Mem->getOffset(); |
| 450 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); |
| 451 int32_t NextOffsetVal = Offset->getValue() + 4; |
| 452 constexpr bool SignExt = false; |
| 453 if (!OperandMIPS32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { |
| 454 // We have to make a temp variable and add 4 to either Base or Offset. |
| 455 // If we add 4 to Offset, this will convert a non-RegReg addressing |
| 456 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows |
| 457 // RegReg addressing modes, prefer adding to base and replacing instead. |
| 458 // Thus we leave the old offset alone. |
| 459 Constant *Four = Ctx->getConstantInt32(4); |
| 460 Variable *NewBase = Func->makeVariable(Base->getType()); |
| 461 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, |
| 462 Base, Four)); |
| 463 Base = NewBase; |
| 464 } else { |
| 465 Offset = |
| 466 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); |
| 467 } |
| 468 return OperandMIPS32Mem::create(Func, SplitType, Base, Offset, |
| 469 Mem->getAddrMode()); |
| 470 } |
| 471 llvm_unreachable("Unsupported operand type"); |
| 472 return nullptr; |
276 } | 473 } |
277 | 474 |
278 llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include, | 475 llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include, |
279 RegSetMask Exclude) const { | 476 RegSetMask Exclude) const { |
280 llvm::SmallBitVector Registers(RegMIPS32::Reg_NUM); | 477 llvm::SmallBitVector Registers(RegMIPS32::Reg_NUM); |
281 | 478 |
282 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 479 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
283 isFP) \ | 480 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
284 if (scratch && (Include & RegSet_CallerSave)) \ | 481 if (scratch && (Include & RegSet_CallerSave)) \ |
285 Registers[RegMIPS32::val] = true; \ | 482 Registers[RegMIPS32::val] = true; \ |
286 if (preserved && (Include & RegSet_CalleeSave)) \ | 483 if (preserved && (Include & RegSet_CalleeSave)) \ |
287 Registers[RegMIPS32::val] = true; \ | 484 Registers[RegMIPS32::val] = true; \ |
288 if (stackptr && (Include & RegSet_StackPointer)) \ | 485 if (stackptr && (Include & RegSet_StackPointer)) \ |
289 Registers[RegMIPS32::val] = true; \ | 486 Registers[RegMIPS32::val] = true; \ |
290 if (frameptr && (Include & RegSet_FramePointer)) \ | 487 if (frameptr && (Include & RegSet_FramePointer)) \ |
291 Registers[RegMIPS32::val] = true; \ | 488 Registers[RegMIPS32::val] = true; \ |
292 if (scratch && (Exclude & RegSet_CallerSave)) \ | 489 if (scratch && (Exclude & RegSet_CallerSave)) \ |
293 Registers[RegMIPS32::val] = false; \ | 490 Registers[RegMIPS32::val] = false; \ |
(...skipping 17 matching lines...) Expand all Loading... |
311 // operations implemented below assume that the stack is aligned before the | 508 // operations implemented below assume that the stack is aligned before the |
312 // alloca. All the alloca code ensures that the stack alignment is preserved | 509 // alloca. All the alloca code ensures that the stack alignment is preserved |
313 // after the alloca. The stack alignment restriction can be relaxed in some | 510 // after the alloca. The stack alignment restriction can be relaxed in some |
314 // cases. | 511 // cases. |
315 NeedsStackAlignment = true; | 512 NeedsStackAlignment = true; |
316 (void)Inst; | 513 (void)Inst; |
317 UnimplementedError(Func->getContext()->getFlags()); | 514 UnimplementedError(Func->getContext()->getFlags()); |
318 } | 515 } |
319 | 516 |
320 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { | 517 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
321 switch (Inst->getOp()) { | 518 Variable *Dest = Inst->getDest(); |
322 case InstArithmetic::_num: | 519 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 520 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 521 (void)Src0; |
| 522 (void)Src1; |
| 523 if (Dest->getType() == IceType_i64) { |
323 UnimplementedError(Func->getContext()->getFlags()); | 524 UnimplementedError(Func->getContext()->getFlags()); |
324 break; | 525 } else if (isVectorType(Dest->getType())) { |
325 case InstArithmetic::Add: | |
326 UnimplementedError(Func->getContext()->getFlags()); | 526 UnimplementedError(Func->getContext()->getFlags()); |
327 break; | 527 } else { // Dest->getType() is non-i64 scalar |
328 case InstArithmetic::And: | 528 switch (Inst->getOp()) { |
329 UnimplementedError(Func->getContext()->getFlags()); | 529 case InstArithmetic::_num: |
330 break; | 530 UnimplementedError(Func->getContext()->getFlags()); |
331 case InstArithmetic::Or: | 531 break; |
332 UnimplementedError(Func->getContext()->getFlags()); | 532 case InstArithmetic::Add: |
333 break; | 533 UnimplementedError(Func->getContext()->getFlags()); |
334 case InstArithmetic::Xor: | 534 // Variable *T = makeReg(Dest->getType()); |
335 UnimplementedError(Func->getContext()->getFlags()); | 535 // _add(T, Src0, Src1); |
336 break; | 536 // _mov(Dest, T); |
337 case InstArithmetic::Sub: | 537 return; |
338 UnimplementedError(Func->getContext()->getFlags()); | 538 case InstArithmetic::And: |
339 break; | 539 UnimplementedError(Func->getContext()->getFlags()); |
340 case InstArithmetic::Mul: | 540 break; |
341 UnimplementedError(Func->getContext()->getFlags()); | 541 case InstArithmetic::Or: |
342 break; | 542 UnimplementedError(Func->getContext()->getFlags()); |
343 case InstArithmetic::Shl: | 543 break; |
344 UnimplementedError(Func->getContext()->getFlags()); | 544 case InstArithmetic::Xor: |
345 break; | 545 UnimplementedError(Func->getContext()->getFlags()); |
346 case InstArithmetic::Lshr: | 546 break; |
347 UnimplementedError(Func->getContext()->getFlags()); | 547 case InstArithmetic::Sub: |
348 break; | 548 UnimplementedError(Func->getContext()->getFlags()); |
349 case InstArithmetic::Ashr: | 549 break; |
350 UnimplementedError(Func->getContext()->getFlags()); | 550 case InstArithmetic::Mul: |
351 break; | 551 UnimplementedError(Func->getContext()->getFlags()); |
352 case InstArithmetic::Udiv: | 552 break; |
353 UnimplementedError(Func->getContext()->getFlags()); | 553 case InstArithmetic::Shl: |
354 break; | 554 UnimplementedError(Func->getContext()->getFlags()); |
355 case InstArithmetic::Sdiv: | 555 break; |
356 UnimplementedError(Func->getContext()->getFlags()); | 556 case InstArithmetic::Lshr: |
357 break; | 557 UnimplementedError(Func->getContext()->getFlags()); |
358 case InstArithmetic::Urem: | 558 break; |
359 UnimplementedError(Func->getContext()->getFlags()); | 559 case InstArithmetic::Ashr: |
360 break; | 560 UnimplementedError(Func->getContext()->getFlags()); |
361 case InstArithmetic::Srem: | 561 break; |
362 UnimplementedError(Func->getContext()->getFlags()); | 562 case InstArithmetic::Udiv: |
363 break; | 563 UnimplementedError(Func->getContext()->getFlags()); |
364 case InstArithmetic::Fadd: | 564 break; |
365 UnimplementedError(Func->getContext()->getFlags()); | 565 case InstArithmetic::Sdiv: |
366 break; | 566 UnimplementedError(Func->getContext()->getFlags()); |
367 case InstArithmetic::Fsub: | 567 break; |
368 UnimplementedError(Func->getContext()->getFlags()); | 568 case InstArithmetic::Urem: |
369 break; | 569 UnimplementedError(Func->getContext()->getFlags()); |
370 case InstArithmetic::Fmul: | 570 break; |
371 UnimplementedError(Func->getContext()->getFlags()); | 571 case InstArithmetic::Srem: |
372 break; | 572 UnimplementedError(Func->getContext()->getFlags()); |
373 case InstArithmetic::Fdiv: | 573 break; |
374 UnimplementedError(Func->getContext()->getFlags()); | 574 case InstArithmetic::Fadd: |
375 break; | 575 UnimplementedError(Func->getContext()->getFlags()); |
376 case InstArithmetic::Frem: | 576 break; |
377 UnimplementedError(Func->getContext()->getFlags()); | 577 case InstArithmetic::Fsub: |
378 break; | 578 UnimplementedError(Func->getContext()->getFlags()); |
| 579 break; |
| 580 case InstArithmetic::Fmul: |
| 581 UnimplementedError(Func->getContext()->getFlags()); |
| 582 break; |
| 583 case InstArithmetic::Fdiv: |
| 584 UnimplementedError(Func->getContext()->getFlags()); |
| 585 break; |
| 586 case InstArithmetic::Frem: |
| 587 UnimplementedError(Func->getContext()->getFlags()); |
| 588 break; |
| 589 } |
379 } | 590 } |
380 } | 591 } |
381 | 592 |
382 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { | 593 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { |
383 (void)Inst; | 594 Variable *Dest = Inst->getDest(); |
384 UnimplementedError(Func->getContext()->getFlags()); | 595 Operand *Src0 = Inst->getSrc(0); |
| 596 assert(Dest->getType() == Src0->getType()); |
| 597 if (Dest->getType() == IceType_i64) { |
| 598 Src0 = legalizeUndef(Src0); |
| 599 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); |
| 600 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); |
| 601 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 602 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 603 // Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 604 Variable *T_Lo = makeReg(IceType_i32); |
| 605 Variable *T_Hi = makeReg(IceType_i32); |
| 606 _mov(T_Lo, Src0Lo); |
| 607 _mov(DestLo, T_Lo); |
| 608 _mov(T_Hi, Src0Hi); |
| 609 _mov(DestHi, T_Hi); |
| 610 } else { |
| 611 Operand *SrcR; |
| 612 if (Dest->hasReg()) { |
| 613 // If Dest already has a physical register, then legalize the Src operand |
| 614 // into a Variable with the same register assignment. This especially |
| 615 // helps allow the use of Flex operands. |
| 616 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); |
| 617 } else { |
| 618 // Dest could be a stack operand. Since we could potentially need |
| 619 // to do a Store (and store can only have Register operands), |
| 620 // legalize this to a register. |
| 621 SrcR = legalize(Src0, Legal_Reg); |
| 622 } |
| 623 if (isVectorType(Dest->getType())) { |
| 624 UnimplementedError(Func->getContext()->getFlags()); |
| 625 } else { |
| 626 _mov(Dest, SrcR); |
| 627 } |
| 628 } |
385 } | 629 } |
386 | 630 |
387 void TargetMIPS32::lowerBr(const InstBr *Inst) { | 631 void TargetMIPS32::lowerBr(const InstBr *Inst) { |
388 (void)Inst; | 632 (void)Inst; |
389 UnimplementedError(Func->getContext()->getFlags()); | 633 UnimplementedError(Func->getContext()->getFlags()); |
390 } | 634 } |
391 | 635 |
392 void TargetMIPS32::lowerCall(const InstCall *Inst) { | 636 void TargetMIPS32::lowerCall(const InstCall *Inst) { |
393 (void)Inst; | 637 (void)Inst; |
394 UnimplementedError(Func->getContext()->getFlags()); | 638 UnimplementedError(Func->getContext()->getFlags()); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 UnimplementedError(Func->getContext()->getFlags()); | 845 UnimplementedError(Func->getContext()->getFlags()); |
602 } | 846 } |
603 } | 847 } |
604 | 848 |
605 void TargetMIPS32::lowerPhi(const InstPhi * /*Inst*/) { | 849 void TargetMIPS32::lowerPhi(const InstPhi * /*Inst*/) { |
606 Func->setError("Phi found in regular instruction list"); | 850 Func->setError("Phi found in regular instruction list"); |
607 } | 851 } |
608 | 852 |
609 void TargetMIPS32::lowerRet(const InstRet *Inst) { | 853 void TargetMIPS32::lowerRet(const InstRet *Inst) { |
610 Variable *Reg = nullptr; | 854 Variable *Reg = nullptr; |
611 if (Inst->hasRetValue()) | 855 if (Inst->hasRetValue()) { |
612 UnimplementedError(Func->getContext()->getFlags()); | 856 Operand *Src0 = Inst->getRetValue(); |
| 857 switch (Src0->getType()) { |
| 858 case IceType_i1: |
| 859 case IceType_i8: |
| 860 case IceType_i16: |
| 861 case IceType_i32: { |
| 862 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); |
| 863 Operand *Src0F = legalize(Src0, Legal_Reg); |
| 864 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); |
| 865 _mov(Reg, Src0F); |
| 866 break; |
| 867 } |
| 868 case IceType_i64: { |
| 869 Src0 = legalizeUndef(Src0); |
| 870 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); |
| 871 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); |
| 872 Reg = R0; |
| 873 Context.insert(InstFakeUse::create(Func, R1)); |
| 874 break; |
| 875 } |
| 876 |
| 877 default: |
| 878 UnimplementedError(Func->getContext()->getFlags()); |
| 879 } |
| 880 } |
613 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); | 881 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); |
614 } | 882 } |
615 | 883 |
616 void TargetMIPS32::lowerSelect(const InstSelect *Inst) { | 884 void TargetMIPS32::lowerSelect(const InstSelect *Inst) { |
617 (void)Inst; | 885 (void)Inst; |
618 UnimplementedError(Func->getContext()->getFlags()); | 886 UnimplementedError(Func->getContext()->getFlags()); |
619 } | 887 } |
620 | 888 |
621 void TargetMIPS32::lowerStore(const InstStore *Inst) { | 889 void TargetMIPS32::lowerStore(const InstStore *Inst) { |
622 (void)Inst; | 890 (void)Inst; |
(...skipping 10 matching lines...) Expand all Loading... |
633 } | 901 } |
634 | 902 |
635 void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 903 void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
636 UnimplementedError(Func->getContext()->getFlags()); | 904 UnimplementedError(Func->getContext()->getFlags()); |
637 } | 905 } |
638 | 906 |
639 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 907 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
640 // integrity of liveness analysis. Undef values are also turned into zeroes, | 908 // integrity of liveness analysis. Undef values are also turned into zeroes, |
641 // since loOperand() and hiOperand() don't expect Undef input. | 909 // since loOperand() and hiOperand() don't expect Undef input. |
642 void TargetMIPS32::prelowerPhis() { | 910 void TargetMIPS32::prelowerPhis() { |
643 UnimplementedError(Func->getContext()->getFlags()); | 911 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); |
644 } | 912 } |
645 | 913 |
646 void TargetMIPS32::postLower() { | 914 void TargetMIPS32::postLower() { |
647 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 915 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
648 return; | 916 return; |
649 // Find two-address non-SSA instructions where Dest==Src0, and set the | 917 // Find two-address non-SSA instructions where Dest==Src0, and set the |
650 // IsDestRedefined flag to keep liveness analysis consistent. | 918 // IsDestRedefined flag to keep liveness analysis consistent. |
651 UnimplementedError(Func->getContext()->getFlags()); | 919 UnimplementedError(Func->getContext()->getFlags()); |
652 } | 920 } |
653 | 921 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 return; | 966 return; |
699 UnimplementedError(Ctx->getFlags()); | 967 UnimplementedError(Ctx->getFlags()); |
700 } | 968 } |
701 | 969 |
702 void TargetDataMIPS32::lowerJumpTables() { | 970 void TargetDataMIPS32::lowerJumpTables() { |
703 if (Ctx->getFlags().getDisableTranslation()) | 971 if (Ctx->getFlags().getDisableTranslation()) |
704 return; | 972 return; |
705 UnimplementedError(Ctx->getFlags()); | 973 UnimplementedError(Ctx->getFlags()); |
706 } | 974 } |
707 | 975 |
| 976 // Helper for legalize() to emit the right code to lower an operand to a |
| 977 // register of the appropriate type. |
| 978 Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) { |
| 979 Type Ty = Src->getType(); |
| 980 Variable *Reg = makeReg(Ty, RegNum); |
| 981 if (isVectorType(Ty) || isFloatingType(Ty)) { |
| 982 UnimplementedError(Ctx->getFlags()); |
| 983 } else { |
| 984 // Mov's Src operand can really only be the flexible second operand type |
| 985 // or a register. Users should guarantee that. |
| 986 _mov(Reg, Src); |
| 987 } |
| 988 return Reg; |
| 989 } |
| 990 |
| 991 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
| 992 int32_t RegNum) { |
| 993 Type Ty = From->getType(); |
| 994 // Assert that a physical register is allowed. To date, all calls |
| 995 // to legalize() allow a physical register. Legal_Flex converts |
| 996 // registers to the right type OperandMIPS32FlexReg as needed. |
| 997 assert(Allowed & Legal_Reg); |
| 998 // Go through the various types of operands: |
| 999 // OperandMIPS32Mem, OperandMIPS32Flex, Constant, and Variable. |
| 1000 // Given the above assertion, if type of operand is not legal |
| 1001 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy |
| 1002 // to a register. |
| 1003 if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 1004 (void)C; |
| 1005 return From; |
| 1006 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 1007 uint32_t Value = static_cast<uint32_t>(C32->getValue()); |
| 1008 // Check if the immediate will fit in a Flexible second operand, |
| 1009 // if a Flexible second operand is allowed. We need to know the exact |
| 1010 // value, so that rules out relocatable constants. |
| 1011 // Also try the inverse and use MVN if possible. |
| 1012 // Do a movw/movt to a register. |
| 1013 Variable *Reg; |
| 1014 if (RegNum == Variable::NoRegister) |
| 1015 Reg = makeReg(Ty, RegNum); |
| 1016 else |
| 1017 Reg = getPhysicalRegister(RegNum); |
| 1018 if (isInt<16>(int32_t(Value))) { |
| 1019 _addiu(Reg, getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty), Value); |
| 1020 } else { |
| 1021 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| 1022 (void)UpperBits; |
| 1023 uint32_t LowerBits = Value & 0xFFFF; |
| 1024 Variable *TReg = makeReg(Ty, RegNum); |
| 1025 _lui(TReg, UpperBits); |
| 1026 _ori(Reg, TReg, LowerBits); |
| 1027 } |
| 1028 return Reg; |
| 1029 } |
| 1030 if (auto Var = llvm::dyn_cast<Variable>(From)) { |
| 1031 // Check if the variable is guaranteed a physical register. This |
| 1032 // can happen either when the variable is pre-colored or when it is |
| 1033 // assigned infinite weight. |
| 1034 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 1035 // We need a new physical register for the operand if: |
| 1036 // Mem is not allowed and Var isn't guaranteed a physical |
| 1037 // register, or |
| 1038 // RegNum is required and Var->getRegNum() doesn't match. |
| 1039 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 1040 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { |
| 1041 From = copyToReg(From, RegNum); |
| 1042 } |
| 1043 return From; |
| 1044 } |
| 1045 return From; |
| 1046 } |
| 1047 |
708 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) | 1048 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) |
709 : TargetHeaderLowering(Ctx) {} | 1049 : TargetHeaderLowering(Ctx) {} |
710 | 1050 |
| 1051 void TargetHeaderMIPS32::lower() { |
| 1052 OstreamLocker L(Ctx); |
| 1053 Ostream &Str = Ctx->getStrEmit(); |
| 1054 Str << "\t.set\tnomicromips\n"; |
| 1055 Str << "\t.set\tnomips16\n"; |
| 1056 } |
| 1057 |
711 } // end of namespace Ice | 1058 } // end of namespace Ice |
OLD | NEW |