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 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 | 533 |
534 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 534 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
535 Variable *Dest = Inst->getDest(); | 535 Variable *Dest = Inst->getDest(); |
536 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier | 536 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
537 // to legalize Src0 to flex or Src1 to flex and there is a reversible | 537 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
538 // instruction. E.g., reverse subtract with immediate, register vs | 538 // instruction. E.g., reverse subtract with immediate, register vs |
539 // register, immediate. | 539 // register, immediate. |
540 // Or it may be the case that the operands aren't swapped, but the | 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. | 541 // bits can be flipped and a different operation applied. |
542 // E.g., use BIC (bit clear) instead of AND for some masks. | 542 // E.g., use BIC (bit clear) instead of AND for some masks. |
543 Variable *Src0 = legalizeToVar(Inst->getSrc(0)); | 543 Operand *Src0 = Inst->getSrc(0); |
544 Operand *Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); | 544 Operand *Src1 = Inst->getSrc(1); |
545 (void)Src0; | |
546 (void)Src1; | |
547 if (Dest->getType() == IceType_i64) { | 545 if (Dest->getType() == IceType_i64) { |
548 UnimplementedError(Func->getContext()->getFlags()); | 546 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 547 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 548 Variable *Src0RLo = legalizeToVar(loOperand(Src0)); |
| 549 Variable *Src0RHi = legalizeToVar(hiOperand(Src0)); |
| 550 Operand *Src1Lo = legalize(loOperand(Src1), Legal_Reg | Legal_Flex); |
| 551 Operand *Src1Hi = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex); |
| 552 Variable *T_Lo = makeReg(DestLo->getType()); |
| 553 Variable *T_Hi = makeReg(DestHi->getType()); |
| 554 switch (Inst->getOp()) { |
| 555 case InstArithmetic::_num: |
| 556 llvm_unreachable("Unknown arithmetic operator"); |
| 557 break; |
| 558 case InstArithmetic::Add: |
| 559 _adds(T_Lo, Src0RLo, Src1Lo); |
| 560 _mov(DestLo, T_Lo); |
| 561 _adc(T_Hi, Src0RHi, Src1Hi); |
| 562 _mov(DestHi, T_Hi); |
| 563 break; |
| 564 case InstArithmetic::And: |
| 565 _and(T_Lo, Src0RLo, Src1Lo); |
| 566 _mov(DestLo, T_Lo); |
| 567 _and(T_Hi, Src0RHi, Src1Hi); |
| 568 _mov(DestHi, T_Hi); |
| 569 break; |
| 570 case InstArithmetic::Or: |
| 571 _orr(T_Lo, Src0RLo, Src1Lo); |
| 572 _mov(DestLo, T_Lo); |
| 573 _orr(T_Hi, Src0RHi, Src1Hi); |
| 574 _mov(DestHi, T_Hi); |
| 575 break; |
| 576 case InstArithmetic::Xor: |
| 577 _eor(T_Lo, Src0RLo, Src1Lo); |
| 578 _mov(DestLo, T_Lo); |
| 579 _eor(T_Hi, Src0RHi, Src1Hi); |
| 580 _mov(DestHi, T_Hi); |
| 581 break; |
| 582 case InstArithmetic::Sub: |
| 583 _subs(T_Lo, Src0RLo, Src1Lo); |
| 584 _mov(DestLo, T_Lo); |
| 585 _sbc(T_Hi, Src0RHi, Src1Hi); |
| 586 _mov(DestHi, T_Hi); |
| 587 break; |
| 588 case InstArithmetic::Mul: { |
| 589 // GCC 4.8 does: |
| 590 // a=b*c ==> |
| 591 // t_acc =(mul) (b.lo * c.hi) |
| 592 // t_acc =(mla) (c.lo * b.hi) + t_acc |
| 593 // t.hi,t.lo =(umull) b.lo * c.lo |
| 594 // t.hi += t_acc |
| 595 // a.lo = t.lo |
| 596 // a.hi = t.hi |
| 597 // |
| 598 // LLVM does: |
| 599 // t.hi,t.lo =(umull) b.lo * c.lo |
| 600 // t.hi =(mla) (b.lo * c.hi) + t.hi |
| 601 // t.hi =(mla) (b.hi * c.lo) + t.hi |
| 602 // a.lo = t.lo |
| 603 // a.hi = t.hi |
| 604 // |
| 605 // LLVM's lowering has fewer instructions, but more register pressure: |
| 606 // t.lo is live from beginning to end, while GCC delays the two-dest |
| 607 // instruction till the end, and kills c.hi immediately. |
| 608 Variable *T_Acc = makeReg(IceType_i32); |
| 609 Variable *T_Acc1 = makeReg(IceType_i32); |
| 610 Variable *T_Hi1 = makeReg(IceType_i32); |
| 611 Variable *Src1RLo = legalizeToVar(Src1Lo); |
| 612 Variable *Src1RHi = legalizeToVar(Src1Hi); |
| 613 _mul(T_Acc, Src0RLo, Src1RHi); |
| 614 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
| 615 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
| 616 _add(T_Hi, T_Hi1, T_Acc1); |
| 617 _mov(DestLo, T_Lo); |
| 618 _mov(DestHi, T_Hi); |
| 619 } break; |
| 620 case InstArithmetic::Shl: |
| 621 case InstArithmetic::Lshr: |
| 622 case InstArithmetic::Ashr: |
| 623 case InstArithmetic::Udiv: |
| 624 case InstArithmetic::Sdiv: |
| 625 case InstArithmetic::Urem: |
| 626 case InstArithmetic::Srem: |
| 627 UnimplementedError(Func->getContext()->getFlags()); |
| 628 break; |
| 629 case InstArithmetic::Fadd: |
| 630 case InstArithmetic::Fsub: |
| 631 case InstArithmetic::Fmul: |
| 632 case InstArithmetic::Fdiv: |
| 633 case InstArithmetic::Frem: |
| 634 llvm_unreachable("FP instruction with i64 type"); |
| 635 break; |
| 636 } |
549 } else if (isVectorType(Dest->getType())) { | 637 } else if (isVectorType(Dest->getType())) { |
550 UnimplementedError(Func->getContext()->getFlags()); | 638 UnimplementedError(Func->getContext()->getFlags()); |
551 } else { // Dest->getType() is non-i64 scalar | 639 } else { // Dest->getType() is non-i64 scalar |
| 640 Variable *Src0R = legalizeToVar(Inst->getSrc(0)); |
| 641 Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); |
| 642 Variable *T = makeReg(Dest->getType()); |
552 switch (Inst->getOp()) { | 643 switch (Inst->getOp()) { |
553 case InstArithmetic::_num: | 644 case InstArithmetic::_num: |
554 llvm_unreachable("Unknown arithmetic operator"); | 645 llvm_unreachable("Unknown arithmetic operator"); |
555 break; | 646 break; |
556 case InstArithmetic::Add: { | 647 case InstArithmetic::Add: { |
557 UnimplementedError(Func->getContext()->getFlags()); | 648 _add(T, Src0R, Src1); |
558 // Variable *T = makeReg(Dest->getType()); | 649 _mov(Dest, T); |
559 // _add(T, Src0, Src1); | |
560 // _mov(Dest, T); | |
561 } break; | 650 } break; |
562 case InstArithmetic::And: | 651 case InstArithmetic::And: { |
563 UnimplementedError(Func->getContext()->getFlags()); | 652 _and(T, Src0R, Src1); |
564 break; | 653 _mov(Dest, T); |
565 case InstArithmetic::Or: | 654 } break; |
566 UnimplementedError(Func->getContext()->getFlags()); | 655 case InstArithmetic::Or: { |
567 break; | 656 _orr(T, Src0R, Src1); |
568 case InstArithmetic::Xor: | 657 _mov(Dest, T); |
569 UnimplementedError(Func->getContext()->getFlags()); | 658 } break; |
570 break; | 659 case InstArithmetic::Xor: { |
571 case InstArithmetic::Sub: | 660 _eor(T, Src0R, Src1); |
572 UnimplementedError(Func->getContext()->getFlags()); | 661 _mov(Dest, T); |
573 break; | 662 } break; |
574 case InstArithmetic::Mul: | 663 case InstArithmetic::Sub: { |
575 UnimplementedError(Func->getContext()->getFlags()); | 664 _sub(T, Src0R, Src1); |
576 break; | 665 _mov(Dest, T); |
| 666 } break; |
| 667 case InstArithmetic::Mul: { |
| 668 Variable *Src1R = legalizeToVar(Src1); |
| 669 _mul(T, Src0R, Src1R); |
| 670 _mov(Dest, T); |
| 671 } break; |
577 case InstArithmetic::Shl: | 672 case InstArithmetic::Shl: |
578 UnimplementedError(Func->getContext()->getFlags()); | 673 UnimplementedError(Func->getContext()->getFlags()); |
579 break; | 674 break; |
580 case InstArithmetic::Lshr: | 675 case InstArithmetic::Lshr: |
581 UnimplementedError(Func->getContext()->getFlags()); | 676 UnimplementedError(Func->getContext()->getFlags()); |
582 break; | 677 break; |
583 case InstArithmetic::Ashr: | 678 case InstArithmetic::Ashr: |
584 UnimplementedError(Func->getContext()->getFlags()); | 679 UnimplementedError(Func->getContext()->getFlags()); |
585 break; | 680 break; |
586 case InstArithmetic::Udiv: | 681 case InstArithmetic::Udiv: |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 } | 1292 } |
1198 } | 1293 } |
1199 | 1294 |
1200 void TargetDataARM32::lowerConstants() const { | 1295 void TargetDataARM32::lowerConstants() const { |
1201 if (Ctx->getFlags().getDisableTranslation()) | 1296 if (Ctx->getFlags().getDisableTranslation()) |
1202 return; | 1297 return; |
1203 UnimplementedError(Ctx->getFlags()); | 1298 UnimplementedError(Ctx->getFlags()); |
1204 } | 1299 } |
1205 | 1300 |
1206 } // end of namespace Ice | 1301 } // end of namespace Ice |
OLD | NEW |