OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 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 // This file implements the TargetLoweringARM32 class, which consists almost | 10 // This file implements the TargetLoweringARM32 class, which consists almost |
(...skipping 21 matching lines...) Expand all Loading... |
32 | 32 |
33 namespace { | 33 namespace { |
34 void UnimplementedError(const ClFlags &Flags) { | 34 void UnimplementedError(const ClFlags &Flags) { |
35 if (!Flags.getSkipUnimplemented()) { | 35 if (!Flags.getSkipUnimplemented()) { |
36 // Use llvm_unreachable instead of report_fatal_error, which gives better | 36 // Use llvm_unreachable instead of report_fatal_error, which gives better |
37 // stack traces. | 37 // stack traces. |
38 llvm_unreachable("Not yet implemented"); | 38 llvm_unreachable("Not yet implemented"); |
39 abort(); | 39 abort(); |
40 } | 40 } |
41 } | 41 } |
| 42 |
| 43 // The maximum number of arguments to pass in GPR registers. |
| 44 const uint32_t ARM32_MAX_GPR_ARG = 4; |
| 45 |
42 } // end of anonymous namespace | 46 } // end of anonymous namespace |
43 | 47 |
44 TargetARM32::TargetARM32(Cfg *Func) | 48 TargetARM32::TargetARM32(Cfg *Func) |
45 : TargetLowering(Func), UsesFramePointer(false) { | 49 : TargetLowering(Func), UsesFramePointer(false) { |
46 // TODO: Don't initialize IntegerRegisters and friends every time. | 50 // TODO: Don't initialize IntegerRegisters and friends every time. |
47 // Instead, initialize in some sort of static initializer for the | 51 // Instead, initialize in some sort of static initializer for the |
48 // class. | 52 // class. |
49 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 53 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
50 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); | 54 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); |
51 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 55 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 int32_t Offset = Var->getStackOffset(); | 272 int32_t Offset = Var->getStackOffset(); |
269 if (!hasFramePointer()) | 273 if (!hasFramePointer()) |
270 Offset += getStackAdjustment(); | 274 Offset += getStackAdjustment(); |
271 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register | 275 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register |
272 // to materialize a larger offset. | 276 // to materialize a larger offset. |
273 const bool SignExt = false; | 277 const bool SignExt = false; |
274 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { | 278 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { |
275 llvm::report_fatal_error("Illegal stack offset"); | 279 llvm::report_fatal_error("Illegal stack offset"); |
276 } | 280 } |
277 const Type FrameSPTy = IceType_i32; | 281 const Type FrameSPTy = IceType_i32; |
278 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy) << ", " << Offset | 282 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy); |
279 << "]"; | 283 if (Offset != 0) { |
| 284 Str << ", " << getConstantPrefix() << Offset; |
| 285 } |
| 286 Str << "]"; |
280 } | 287 } |
281 | 288 |
282 void TargetARM32::lowerArguments() { | 289 void TargetARM32::lowerArguments() { |
283 UnimplementedError(Func->getContext()->getFlags()); | 290 VarList &Args = Func->getArgs(); |
| 291 // The first few integer type parameters can use r0-r3, regardless of their |
| 292 // position relative to the floating-point/vector arguments in the argument |
| 293 // list. Floating-point and vector arguments can use q0-q3 (aka d0-d7, |
| 294 // s0-s15). |
| 295 unsigned NumGPRRegsUsed = 0; |
| 296 |
| 297 // For each register argument, replace Arg in the argument list with the |
| 298 // home register. Then generate an instruction in the prolog to copy the |
| 299 // home register to the assigned location of Arg. |
| 300 Context.init(Func->getEntryNode()); |
| 301 Context.setInsertPoint(Context.getCur()); |
| 302 |
| 303 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 304 Variable *Arg = Args[I]; |
| 305 Type Ty = Arg->getType(); |
| 306 // TODO(jvoung): handle float/vector types. |
| 307 if (isVectorType(Ty)) { |
| 308 UnimplementedError(Func->getContext()->getFlags()); |
| 309 continue; |
| 310 } else if (isFloatingType(Ty)) { |
| 311 UnimplementedError(Func->getContext()->getFlags()); |
| 312 continue; |
| 313 } else if (Ty == IceType_i64) { |
| 314 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 315 continue; |
| 316 int32_t RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; |
| 317 int32_t RegHi = 0; |
| 318 ++NumGPRRegsUsed; |
| 319 // Always start i64 registers at an even register, so this may end |
| 320 // up padding away a register. |
| 321 if (RegLo % 2 != 0) { |
| 322 ++RegLo; |
| 323 ++NumGPRRegsUsed; |
| 324 } |
| 325 // If this leaves us without room to consume another register, |
| 326 // leave any previously speculatively consumed registers as consumed. |
| 327 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 328 continue; |
| 329 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; |
| 330 ++NumGPRRegsUsed; |
| 331 Variable *RegisterArg = Func->makeVariable(Ty); |
| 332 Variable *RegisterLo = Func->makeVariable(IceType_i32); |
| 333 Variable *RegisterHi = Func->makeVariable(IceType_i32); |
| 334 if (ALLOW_DUMP) { |
| 335 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 336 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); |
| 337 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); |
| 338 } |
| 339 RegisterLo->setRegNum(RegLo); |
| 340 RegisterLo->setIsArg(); |
| 341 RegisterHi->setRegNum(RegHi); |
| 342 RegisterHi->setIsArg(); |
| 343 RegisterArg->setLoHi(RegisterLo, RegisterHi); |
| 344 RegisterArg->setIsArg(); |
| 345 Arg->setIsArg(false); |
| 346 |
| 347 Args[I] = RegisterArg; |
| 348 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 349 continue; |
| 350 } else { |
| 351 assert(Ty == IceType_i32); |
| 352 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 353 continue; |
| 354 int32_t RegNum = RegARM32::Reg_r0 + NumGPRRegsUsed; |
| 355 ++NumGPRRegsUsed; |
| 356 Variable *RegisterArg = Func->makeVariable(Ty); |
| 357 if (ALLOW_DUMP) { |
| 358 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 359 } |
| 360 RegisterArg->setRegNum(RegNum); |
| 361 RegisterArg->setIsArg(); |
| 362 Arg->setIsArg(false); |
| 363 |
| 364 Args[I] = RegisterArg; |
| 365 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 366 } |
| 367 } |
284 } | 368 } |
285 | 369 |
286 Type TargetARM32::stackSlotType() { return IceType_i32; } | 370 Type TargetARM32::stackSlotType() { return IceType_i32; } |
287 | 371 |
288 void TargetARM32::addProlog(CfgNode *Node) { | 372 void TargetARM32::addProlog(CfgNode *Node) { |
289 (void)Node; | 373 (void)Node; |
290 UnimplementedError(Func->getContext()->getFlags()); | 374 UnimplementedError(Func->getContext()->getFlags()); |
291 } | 375 } |
292 | 376 |
293 void TargetARM32::addEpilog(CfgNode *Node) { | 377 void TargetARM32::addEpilog(CfgNode *Node) { |
294 (void)Node; | 378 (void)Node; |
295 UnimplementedError(Func->getContext()->getFlags()); | 379 UnimplementedError(Func->getContext()->getFlags()); |
296 } | 380 } |
297 | 381 |
| 382 void TargetARM32::split64(Variable *Var) { |
| 383 assert(Var->getType() == IceType_i64); |
| 384 Variable *Lo = Var->getLo(); |
| 385 Variable *Hi = Var->getHi(); |
| 386 if (Lo) { |
| 387 assert(Hi); |
| 388 return; |
| 389 } |
| 390 assert(Hi == nullptr); |
| 391 Lo = Func->makeVariable(IceType_i32); |
| 392 Hi = Func->makeVariable(IceType_i32); |
| 393 if (ALLOW_DUMP) { |
| 394 Lo->setName(Func, Var->getName(Func) + "__lo"); |
| 395 Hi->setName(Func, Var->getName(Func) + "__hi"); |
| 396 } |
| 397 Var->setLoHi(Lo, Hi); |
| 398 if (Var->getIsArg()) { |
| 399 Lo->setIsArg(); |
| 400 Hi->setIsArg(); |
| 401 } |
| 402 } |
| 403 |
| 404 Operand *TargetARM32::loOperand(Operand *Operand) { |
| 405 assert(Operand->getType() == IceType_i64); |
| 406 if (Operand->getType() != IceType_i64) |
| 407 return Operand; |
| 408 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 409 split64(Var); |
| 410 return Var->getLo(); |
| 411 } |
| 412 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 413 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 414 } |
| 415 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 416 // Conservatively disallow memory operands with side-effects (pre/post |
| 417 // increment) in case of duplication. |
| 418 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 419 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 420 if (Mem->isRegReg()) { |
| 421 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 422 Mem->getIndex(), Mem->getShiftOp(), |
| 423 Mem->getShiftAmt(), Mem->getAddrMode()); |
| 424 } else { |
| 425 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), |
| 426 Mem->getOffset(), Mem->getAddrMode()); |
| 427 } |
| 428 } |
| 429 llvm_unreachable("Unsupported operand type"); |
| 430 return nullptr; |
| 431 } |
| 432 |
| 433 Operand *TargetARM32::hiOperand(Operand *Operand) { |
| 434 assert(Operand->getType() == IceType_i64); |
| 435 if (Operand->getType() != IceType_i64) |
| 436 return Operand; |
| 437 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 438 split64(Var); |
| 439 return Var->getHi(); |
| 440 } |
| 441 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 442 return Ctx->getConstantInt32( |
| 443 static_cast<uint32_t>(Const->getValue() >> 32)); |
| 444 } |
| 445 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
| 446 // Conservatively disallow memory operands with side-effects |
| 447 // in case of duplication. |
| 448 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
| 449 Mem->getAddrMode() == OperandARM32Mem::NegOffset); |
| 450 const Type SplitType = IceType_i32; |
| 451 if (Mem->isRegReg()) { |
| 452 // We have to make a temp variable T, and add 4 to either Base or Index. |
| 453 // The Index may be shifted, so adding 4 can mean something else. |
| 454 // Thus, prefer T := Base + 4, and use T as the new Base. |
| 455 Variable *Base = Mem->getBase(); |
| 456 Constant *Four = Ctx->getConstantInt32(4); |
| 457 Variable *NewBase = Func->makeVariable(Base->getType()); |
| 458 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, |
| 459 Base, Four)); |
| 460 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), |
| 461 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 462 Mem->getAddrMode()); |
| 463 } else { |
| 464 Variable *Base = Mem->getBase(); |
| 465 ConstantInteger32 *Offset = Mem->getOffset(); |
| 466 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); |
| 467 int32_t NextOffsetVal = Offset->getValue() + 4; |
| 468 const bool SignExt = false; |
| 469 if (!OperandARM32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { |
| 470 // We have to make a temp variable and add 4 to either Base or Offset. |
| 471 // If we add 4 to Offset, this will convert a non-RegReg addressing |
| 472 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows |
| 473 // RegReg addressing modes, prefer adding to base and replacing instead. |
| 474 // Thus we leave the old offset alone. |
| 475 Constant *Four = Ctx->getConstantInt32(4); |
| 476 Variable *NewBase = Func->makeVariable(Base->getType()); |
| 477 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, |
| 478 NewBase, Base, Four)); |
| 479 Base = NewBase; |
| 480 } else { |
| 481 Offset = |
| 482 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); |
| 483 } |
| 484 return OperandARM32Mem::create(Func, SplitType, Base, Offset, |
| 485 Mem->getAddrMode()); |
| 486 } |
| 487 } |
| 488 llvm_unreachable("Unsupported operand type"); |
| 489 return nullptr; |
| 490 } |
| 491 |
298 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 492 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
299 RegSetMask Exclude) const { | 493 RegSetMask Exclude) const { |
300 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 494 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
301 | 495 |
302 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 496 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
303 isFP) \ | 497 isFP) \ |
304 if (scratch && (Include & RegSet_CallerSave)) \ | 498 if (scratch && (Include & RegSet_CallerSave)) \ |
305 Registers[RegARM32::val] = true; \ | 499 Registers[RegARM32::val] = true; \ |
306 if (preserved && (Include & RegSet_CalleeSave)) \ | 500 if (preserved && (Include & RegSet_CalleeSave)) \ |
307 Registers[RegARM32::val] = true; \ | 501 Registers[RegARM32::val] = true; \ |
(...skipping 23 matching lines...) Expand all Loading... |
331 // adjustment operations implemented below assume that the stack is | 525 // adjustment operations implemented below assume that the stack is |
332 // aligned before the alloca. All the alloca code ensures that the | 526 // aligned before the alloca. All the alloca code ensures that the |
333 // stack alignment is preserved after the alloca. The stack alignment | 527 // stack alignment is preserved after the alloca. The stack alignment |
334 // restriction can be relaxed in some cases. | 528 // restriction can be relaxed in some cases. |
335 NeedsStackAlignment = true; | 529 NeedsStackAlignment = true; |
336 (void)Inst; | 530 (void)Inst; |
337 UnimplementedError(Func->getContext()->getFlags()); | 531 UnimplementedError(Func->getContext()->getFlags()); |
338 } | 532 } |
339 | 533 |
340 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 534 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
341 switch (Inst->getOp()) { | 535 Variable *Dest = Inst->getDest(); |
342 case InstArithmetic::_num: | 536 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
343 llvm_unreachable("Unknown arithmetic operator"); | 537 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
344 break; | 538 // instruction. E.g., reverse subtract with immediate, register vs |
345 case InstArithmetic::Add: | 539 // register, immediate. |
| 540 // Or it may be the case that the operands aren't swapped, but the |
| 541 // bits can be flipped and a different operation applied. |
| 542 // E.g., use BIC (bit clear) instead of AND for some masks. |
| 543 Variable *Src0 = legalizeToVar(Inst->getSrc(0)); |
| 544 Operand *Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); |
| 545 (void)Src0; |
| 546 (void)Src1; |
| 547 if (Dest->getType() == IceType_i64) { |
346 UnimplementedError(Func->getContext()->getFlags()); | 548 UnimplementedError(Func->getContext()->getFlags()); |
347 break; | 549 } else if (isVectorType(Dest->getType())) { |
348 case InstArithmetic::And: | |
349 UnimplementedError(Func->getContext()->getFlags()); | 550 UnimplementedError(Func->getContext()->getFlags()); |
350 break; | 551 } else { // Dest->getType() is non-i64 scalar |
351 case InstArithmetic::Or: | 552 switch (Inst->getOp()) { |
352 UnimplementedError(Func->getContext()->getFlags()); | 553 case InstArithmetic::_num: |
353 break; | 554 llvm_unreachable("Unknown arithmetic operator"); |
354 case InstArithmetic::Xor: | 555 break; |
355 UnimplementedError(Func->getContext()->getFlags()); | 556 case InstArithmetic::Add: { |
356 break; | 557 UnimplementedError(Func->getContext()->getFlags()); |
357 case InstArithmetic::Sub: | 558 // Variable *T = makeReg(Dest->getType()); |
358 UnimplementedError(Func->getContext()->getFlags()); | 559 // _add(T, Src0, Src1); |
359 break; | 560 // _mov(Dest, T); |
360 case InstArithmetic::Mul: | 561 } break; |
361 UnimplementedError(Func->getContext()->getFlags()); | 562 case InstArithmetic::And: |
362 break; | 563 UnimplementedError(Func->getContext()->getFlags()); |
363 case InstArithmetic::Shl: | 564 break; |
364 UnimplementedError(Func->getContext()->getFlags()); | 565 case InstArithmetic::Or: |
365 break; | 566 UnimplementedError(Func->getContext()->getFlags()); |
366 case InstArithmetic::Lshr: | 567 break; |
367 UnimplementedError(Func->getContext()->getFlags()); | 568 case InstArithmetic::Xor: |
368 break; | 569 UnimplementedError(Func->getContext()->getFlags()); |
369 case InstArithmetic::Ashr: | 570 break; |
370 UnimplementedError(Func->getContext()->getFlags()); | 571 case InstArithmetic::Sub: |
371 break; | 572 UnimplementedError(Func->getContext()->getFlags()); |
372 case InstArithmetic::Udiv: | 573 break; |
373 UnimplementedError(Func->getContext()->getFlags()); | 574 case InstArithmetic::Mul: |
374 break; | 575 UnimplementedError(Func->getContext()->getFlags()); |
375 case InstArithmetic::Sdiv: | 576 break; |
376 UnimplementedError(Func->getContext()->getFlags()); | 577 case InstArithmetic::Shl: |
377 break; | 578 UnimplementedError(Func->getContext()->getFlags()); |
378 case InstArithmetic::Urem: | 579 break; |
379 UnimplementedError(Func->getContext()->getFlags()); | 580 case InstArithmetic::Lshr: |
380 break; | 581 UnimplementedError(Func->getContext()->getFlags()); |
381 case InstArithmetic::Srem: | 582 break; |
382 UnimplementedError(Func->getContext()->getFlags()); | 583 case InstArithmetic::Ashr: |
383 break; | 584 UnimplementedError(Func->getContext()->getFlags()); |
384 case InstArithmetic::Fadd: | 585 break; |
385 UnimplementedError(Func->getContext()->getFlags()); | 586 case InstArithmetic::Udiv: |
386 break; | 587 UnimplementedError(Func->getContext()->getFlags()); |
387 case InstArithmetic::Fsub: | 588 break; |
388 UnimplementedError(Func->getContext()->getFlags()); | 589 case InstArithmetic::Sdiv: |
389 break; | 590 UnimplementedError(Func->getContext()->getFlags()); |
390 case InstArithmetic::Fmul: | 591 break; |
391 UnimplementedError(Func->getContext()->getFlags()); | 592 case InstArithmetic::Urem: |
392 break; | 593 UnimplementedError(Func->getContext()->getFlags()); |
393 case InstArithmetic::Fdiv: | 594 break; |
394 UnimplementedError(Func->getContext()->getFlags()); | 595 case InstArithmetic::Srem: |
395 break; | 596 UnimplementedError(Func->getContext()->getFlags()); |
396 case InstArithmetic::Frem: | 597 break; |
397 UnimplementedError(Func->getContext()->getFlags()); | 598 case InstArithmetic::Fadd: |
398 break; | 599 UnimplementedError(Func->getContext()->getFlags()); |
| 600 break; |
| 601 case InstArithmetic::Fsub: |
| 602 UnimplementedError(Func->getContext()->getFlags()); |
| 603 break; |
| 604 case InstArithmetic::Fmul: |
| 605 UnimplementedError(Func->getContext()->getFlags()); |
| 606 break; |
| 607 case InstArithmetic::Fdiv: |
| 608 UnimplementedError(Func->getContext()->getFlags()); |
| 609 break; |
| 610 case InstArithmetic::Frem: |
| 611 UnimplementedError(Func->getContext()->getFlags()); |
| 612 break; |
| 613 } |
399 } | 614 } |
400 } | 615 } |
401 | 616 |
402 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 617 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
403 (void)Inst; | 618 Variable *Dest = Inst->getDest(); |
404 UnimplementedError(Func->getContext()->getFlags()); | 619 Operand *Src0 = Inst->getSrc(0); |
| 620 assert(Dest->getType() == Src0->getType()); |
| 621 if (Dest->getType() == IceType_i64) { |
| 622 Src0 = legalize(Src0); |
| 623 Operand *Src0Lo = loOperand(Src0); |
| 624 Operand *Src0Hi = hiOperand(Src0); |
| 625 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 626 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 627 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 628 _mov(T_Lo, Src0Lo); |
| 629 _mov(DestLo, T_Lo); |
| 630 _mov(T_Hi, Src0Hi); |
| 631 _mov(DestHi, T_Hi); |
| 632 } else { |
| 633 Operand *SrcR; |
| 634 if (Dest->hasReg()) { |
| 635 // If Dest already has a physical register, then legalize the |
| 636 // Src operand into a Variable with the same register |
| 637 // assignment. This is mostly a workaround for advanced phi |
| 638 // lowering's ad-hoc register allocation which assumes no |
| 639 // register allocation is needed when at least one of the |
| 640 // operands is non-memory. |
| 641 // TODO(jvoung): check this for ARM. |
| 642 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); |
| 643 } else { |
| 644 // Dest could be a stack operand. Since we could potentially need |
| 645 // to do a Store (and store can only have Register operands), |
| 646 // legalize this to a register. |
| 647 SrcR = legalize(Src0, Legal_Reg); |
| 648 } |
| 649 if (isVectorType(Dest->getType())) { |
| 650 UnimplementedError(Func->getContext()->getFlags()); |
| 651 } else { |
| 652 _mov(Dest, SrcR); |
| 653 } |
| 654 } |
405 } | 655 } |
406 | 656 |
407 void TargetARM32::lowerBr(const InstBr *Inst) { | 657 void TargetARM32::lowerBr(const InstBr *Inst) { |
408 (void)Inst; | 658 (void)Inst; |
409 UnimplementedError(Func->getContext()->getFlags()); | 659 UnimplementedError(Func->getContext()->getFlags()); |
410 } | 660 } |
411 | 661 |
412 void TargetARM32::lowerCall(const InstCall *Inst) { | 662 void TargetARM32::lowerCall(const InstCall *Inst) { |
413 (void)Inst; | 663 (void)Inst; |
414 UnimplementedError(Func->getContext()->getFlags()); | 664 UnimplementedError(Func->getContext()->getFlags()); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 } | 872 } |
623 } | 873 } |
624 | 874 |
625 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 875 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
626 Func->setError("Phi found in regular instruction list"); | 876 Func->setError("Phi found in regular instruction list"); |
627 } | 877 } |
628 | 878 |
629 void TargetARM32::lowerRet(const InstRet *Inst) { | 879 void TargetARM32::lowerRet(const InstRet *Inst) { |
630 Variable *Reg = nullptr; | 880 Variable *Reg = nullptr; |
631 if (Inst->hasRetValue()) { | 881 if (Inst->hasRetValue()) { |
632 UnimplementedError(Func->getContext()->getFlags()); | 882 Operand *Src0 = Inst->getRetValue(); |
| 883 if (Src0->getType() == IceType_i64) { |
| 884 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); |
| 885 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); |
| 886 Reg = R0; |
| 887 Context.insert(InstFakeUse::create(Func, R1)); |
| 888 } else if (isScalarFloatingType(Src0->getType())) { |
| 889 UnimplementedError(Func->getContext()->getFlags()); |
| 890 } else if (isVectorType(Src0->getType())) { |
| 891 UnimplementedError(Func->getContext()->getFlags()); |
| 892 } else { |
| 893 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 894 _mov(Reg, Src0F, RegARM32::Reg_r0); |
| 895 } |
633 } | 896 } |
634 // Add a ret instruction even if sandboxing is enabled, because | 897 // Add a ret instruction even if sandboxing is enabled, because |
635 // addEpilog explicitly looks for a ret instruction as a marker for | 898 // addEpilog explicitly looks for a ret instruction as a marker for |
636 // where to insert the frame removal instructions. | 899 // where to insert the frame removal instructions. |
637 // addEpilog is responsible for restoring the "lr" register as needed | 900 // addEpilog is responsible for restoring the "lr" register as needed |
638 // prior to this ret instruction. | 901 // prior to this ret instruction. |
639 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 902 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
640 // Add a fake use of sp to make sure sp stays alive for the entire | 903 // Add a fake use of sp to make sure sp stays alive for the entire |
641 // function. Otherwise post-call sp adjustments get dead-code | 904 // function. Otherwise post-call sp adjustments get dead-code |
642 // eliminated. TODO: Are there more places where the fake use | 905 // eliminated. TODO: Are there more places where the fake use |
(...skipping 16 matching lines...) Expand all Loading... |
659 void TargetARM32::doAddressOptStore() { | 922 void TargetARM32::doAddressOptStore() { |
660 UnimplementedError(Func->getContext()->getFlags()); | 923 UnimplementedError(Func->getContext()->getFlags()); |
661 } | 924 } |
662 | 925 |
663 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 926 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
664 (void)Inst; | 927 (void)Inst; |
665 UnimplementedError(Func->getContext()->getFlags()); | 928 UnimplementedError(Func->getContext()->getFlags()); |
666 } | 929 } |
667 | 930 |
668 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 931 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
669 llvm_unreachable("Not yet implemented"); | 932 UnimplementedError(Func->getContext()->getFlags()); |
670 } | 933 } |
671 | 934 |
672 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to | 935 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to |
673 // preserve integrity of liveness analysis. Undef values are also | 936 // preserve integrity of liveness analysis. Undef values are also |
674 // turned into zeroes, since loOperand() and hiOperand() don't expect | 937 // turned into zeroes, since loOperand() and hiOperand() don't expect |
675 // Undef input. | 938 // Undef input. |
676 void TargetARM32::prelowerPhis() { | 939 void TargetARM32::prelowerPhis() { |
677 UnimplementedError(Func->getContext()->getFlags()); | 940 UnimplementedError(Func->getContext()->getFlags()); |
678 } | 941 } |
679 | 942 |
680 // Lower the pre-ordered list of assignments into mov instructions. | 943 // Lower the pre-ordered list of assignments into mov instructions. |
681 // Also has to do some ad-hoc register allocation as necessary. | 944 // Also has to do some ad-hoc register allocation as necessary. |
682 void TargetARM32::lowerPhiAssignments(CfgNode *Node, | 945 void TargetARM32::lowerPhiAssignments(CfgNode *Node, |
683 const AssignList &Assignments) { | 946 const AssignList &Assignments) { |
684 (void)Node; | 947 (void)Node; |
685 (void)Assignments; | 948 (void)Assignments; |
686 UnimplementedError(Func->getContext()->getFlags()); | 949 UnimplementedError(Func->getContext()->getFlags()); |
687 } | 950 } |
688 | 951 |
| 952 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 953 Variable *Reg = makeReg(Ty, RegNum); |
| 954 UnimplementedError(Func->getContext()->getFlags()); |
| 955 return Reg; |
| 956 } |
| 957 |
| 958 // Helper for legalize() to emit the right code to lower an operand to a |
| 959 // register of the appropriate type. |
| 960 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
| 961 Type Ty = Src->getType(); |
| 962 Variable *Reg = makeReg(Ty, RegNum); |
| 963 if (isVectorType(Ty)) { |
| 964 UnimplementedError(Func->getContext()->getFlags()); |
| 965 } else { |
| 966 // Mov's Src operand can really only be the flexible second operand type |
| 967 // or a register. Users should guarantee that. |
| 968 _mov(Reg, Src); |
| 969 } |
| 970 return Reg; |
| 971 } |
| 972 |
| 973 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 974 int32_t RegNum) { |
| 975 // Assert that a physical register is allowed. To date, all calls |
| 976 // to legalize() allow a physical register. Legal_Flex converts |
| 977 // registers to the right type OperandARM32FlexReg as needed. |
| 978 assert(Allowed & Legal_Reg); |
| 979 // Go through the various types of operands: |
| 980 // OperandARM32Mem, OperandARM32Flex, Constant, and Variable. |
| 981 // Given the above assertion, if type of operand is not legal |
| 982 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy |
| 983 // to a register. |
| 984 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { |
| 985 // Before doing anything with a Mem operand, we need to ensure |
| 986 // that the Base and Index components are in physical registers. |
| 987 Variable *Base = Mem->getBase(); |
| 988 Variable *Index = Mem->getIndex(); |
| 989 Variable *RegBase = nullptr; |
| 990 Variable *RegIndex = nullptr; |
| 991 if (Base) { |
| 992 RegBase = legalizeToVar(Base); |
| 993 } |
| 994 if (Index) { |
| 995 RegIndex = legalizeToVar(Index); |
| 996 } |
| 997 // Create a new operand if there was a change. |
| 998 if (Base != RegBase || Index != RegIndex) { |
| 999 // There is only a reg +/- reg or reg + imm form. |
| 1000 // Figure out which to re-create. |
| 1001 if (Mem->isRegReg()) { |
| 1002 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, RegIndex, |
| 1003 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 1004 Mem->getAddrMode()); |
| 1005 } else { |
| 1006 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, |
| 1007 Mem->getOffset(), Mem->getAddrMode()); |
| 1008 } |
| 1009 } |
| 1010 if (!(Allowed & Legal_Mem)) { |
| 1011 Type Ty = Mem->getType(); |
| 1012 Variable *Reg = makeReg(Ty, RegNum); |
| 1013 _ldr(Reg, Mem); |
| 1014 From = Reg; |
| 1015 } else { |
| 1016 From = Mem; |
| 1017 } |
| 1018 return From; |
| 1019 } |
| 1020 |
| 1021 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
| 1022 if (!(Allowed & Legal_Flex)) { |
| 1023 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
| 1024 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { |
| 1025 From = FlexReg->getReg(); |
| 1026 // Fall through and let From be checked as a Variable below, |
| 1027 // where it may or may not need a register. |
| 1028 } else { |
| 1029 return copyToReg(Flex, RegNum); |
| 1030 } |
| 1031 } else { |
| 1032 return copyToReg(Flex, RegNum); |
| 1033 } |
| 1034 } else { |
| 1035 return From; |
| 1036 } |
| 1037 } |
| 1038 |
| 1039 if (llvm::isa<Constant>(From)) { |
| 1040 if (llvm::isa<ConstantUndef>(From)) { |
| 1041 // Lower undefs to zero. Another option is to lower undefs to an |
| 1042 // uninitialized register; however, using an uninitialized register |
| 1043 // results in less predictable code. |
| 1044 if (isVectorType(From->getType())) |
| 1045 return makeVectorOfZeros(From->getType(), RegNum); |
| 1046 From = Ctx->getConstantZero(From->getType()); |
| 1047 } |
| 1048 // There should be no constants of vector type (other than undef). |
| 1049 assert(!isVectorType(From->getType())); |
| 1050 bool CanBeFlex = Allowed & Legal_Flex; |
| 1051 if (auto C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 1052 uint32_t RotateAmt; |
| 1053 uint32_t Immed_8; |
| 1054 uint32_t Value = static_cast<uint32_t>(C32->getValue()); |
| 1055 // Check if the immediate will fit in a Flexible second operand, |
| 1056 // if a Flexible second operand is allowed. We need to know the exact |
| 1057 // value, so that rules out relocatable constants. |
| 1058 // Also try the inverse and use MVN if possible. |
| 1059 if (CanBeFlex && |
| 1060 OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { |
| 1061 return OperandARM32FlexImm::create(Func, From->getType(), Immed_8, |
| 1062 RotateAmt); |
| 1063 } else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( |
| 1064 ~Value, &RotateAmt, &Immed_8)) { |
| 1065 auto InvertedFlex = OperandARM32FlexImm::create(Func, From->getType(), |
| 1066 Immed_8, RotateAmt); |
| 1067 Type Ty = From->getType(); |
| 1068 Variable *Reg = makeReg(Ty, RegNum); |
| 1069 _mvn(Reg, InvertedFlex); |
| 1070 return Reg; |
| 1071 } else { |
| 1072 // Do a movw/movt to a register. |
| 1073 Type Ty = From->getType(); |
| 1074 Variable *Reg = makeReg(Ty, RegNum); |
| 1075 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| 1076 _movw(Reg, |
| 1077 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); |
| 1078 if (UpperBits != 0) { |
| 1079 _movt(Reg, Ctx->getConstantInt32(UpperBits)); |
| 1080 } |
| 1081 return Reg; |
| 1082 } |
| 1083 } else if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 1084 Type Ty = From->getType(); |
| 1085 Variable *Reg = makeReg(Ty, RegNum); |
| 1086 _movw(Reg, C); |
| 1087 _movt(Reg, C); |
| 1088 return Reg; |
| 1089 } else { |
| 1090 // Load floats/doubles from literal pool. |
| 1091 UnimplementedError(Func->getContext()->getFlags()); |
| 1092 From = copyToReg(From, RegNum); |
| 1093 } |
| 1094 return From; |
| 1095 } |
| 1096 |
| 1097 if (auto Var = llvm::dyn_cast<Variable>(From)) { |
| 1098 // Check if the variable is guaranteed a physical register. This |
| 1099 // can happen either when the variable is pre-colored or when it is |
| 1100 // assigned infinite weight. |
| 1101 bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); |
| 1102 // We need a new physical register for the operand if: |
| 1103 // Mem is not allowed and Var isn't guaranteed a physical |
| 1104 // register, or |
| 1105 // RegNum is required and Var->getRegNum() doesn't match. |
| 1106 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 1107 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { |
| 1108 From = copyToReg(From, RegNum); |
| 1109 } |
| 1110 return From; |
| 1111 } |
| 1112 llvm_unreachable("Unhandled operand kind in legalize()"); |
| 1113 |
| 1114 return From; |
| 1115 } |
| 1116 |
| 1117 // Provide a trivial wrapper to legalize() for this common usage. |
| 1118 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { |
| 1119 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 1120 } |
| 1121 |
| 1122 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { |
| 1123 // There aren't any 64-bit integer registers for ARM32. |
| 1124 assert(Type != IceType_i64); |
| 1125 Variable *Reg = Func->makeVariable(Type); |
| 1126 if (RegNum == Variable::NoRegister) |
| 1127 Reg->setWeightInfinite(); |
| 1128 else |
| 1129 Reg->setRegNum(RegNum); |
| 1130 return Reg; |
| 1131 } |
| 1132 |
689 void TargetARM32::postLower() { | 1133 void TargetARM32::postLower() { |
690 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 1134 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
691 return; | 1135 return; |
692 // Find two-address non-SSA instructions where Dest==Src0, and set | 1136 inferTwoAddress(); |
693 // the DestNonKillable flag to keep liveness analysis consistent. | |
694 UnimplementedError(Func->getContext()->getFlags()); | |
695 } | 1137 } |
696 | 1138 |
697 void TargetARM32::makeRandomRegisterPermutation( | 1139 void TargetARM32::makeRandomRegisterPermutation( |
698 llvm::SmallVectorImpl<int32_t> &Permutation, | 1140 llvm::SmallVectorImpl<int32_t> &Permutation, |
699 const llvm::SmallBitVector &ExcludeRegisters) const { | 1141 const llvm::SmallBitVector &ExcludeRegisters) const { |
700 (void)Permutation; | 1142 (void)Permutation; |
701 (void)ExcludeRegisters; | 1143 (void)ExcludeRegisters; |
702 UnimplementedError(Func->getContext()->getFlags()); | 1144 UnimplementedError(Func->getContext()->getFlags()); |
703 } | 1145 } |
704 | 1146 |
705 void TargetARM32::emit(const ConstantInteger32 *C) const { | 1147 void TargetARM32::emit(const ConstantInteger32 *C) const { |
706 if (!ALLOW_DUMP) | 1148 if (!ALLOW_DUMP) |
707 return; | 1149 return; |
708 Ostream &Str = Ctx->getStrEmit(); | 1150 Ostream &Str = Ctx->getStrEmit(); |
709 Str << getConstantPrefix() << C->getValue(); | 1151 Str << getConstantPrefix() << C->getValue(); |
710 } | 1152 } |
711 | 1153 |
712 void TargetARM32::emit(const ConstantInteger64 *) const { | 1154 void TargetARM32::emit(const ConstantInteger64 *) const { |
713 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 1155 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
714 } | 1156 } |
715 | 1157 |
716 void TargetARM32::emit(const ConstantFloat *C) const { | 1158 void TargetARM32::emit(const ConstantFloat *C) const { |
| 1159 (void)C; |
717 UnimplementedError(Ctx->getFlags()); | 1160 UnimplementedError(Ctx->getFlags()); |
718 } | 1161 } |
719 | 1162 |
720 void TargetARM32::emit(const ConstantDouble *C) const { | 1163 void TargetARM32::emit(const ConstantDouble *C) const { |
| 1164 (void)C; |
721 UnimplementedError(Ctx->getFlags()); | 1165 UnimplementedError(Ctx->getFlags()); |
722 } | 1166 } |
723 | 1167 |
724 void TargetARM32::emit(const ConstantUndef *) const { | 1168 void TargetARM32::emit(const ConstantUndef *) const { |
725 llvm::report_fatal_error("undef value encountered by emitter."); | 1169 llvm::report_fatal_error("undef value encountered by emitter."); |
726 } | 1170 } |
727 | 1171 |
728 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 1172 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
729 : TargetDataLowering(Ctx) {} | 1173 : TargetDataLowering(Ctx) {} |
730 | 1174 |
(...skipping 22 matching lines...) Expand all Loading... |
753 } | 1197 } |
754 } | 1198 } |
755 | 1199 |
756 void TargetDataARM32::lowerConstants() const { | 1200 void TargetDataARM32::lowerConstants() const { |
757 if (Ctx->getFlags().getDisableTranslation()) | 1201 if (Ctx->getFlags().getDisableTranslation()) |
758 return; | 1202 return; |
759 UnimplementedError(Ctx->getFlags()); | 1203 UnimplementedError(Ctx->getFlags()); |
760 } | 1204 } |
761 | 1205 |
762 } // end of namespace Ice | 1206 } // end of namespace Ice |
OLD | NEW |