Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1127963004: Subzero ARM: lowerArguments (GPR), basic legalize(), and lowerRet(i32, i64). (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: fix warnings, etc Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698