| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 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 TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
| (...skipping 3529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3540 else | 3540 else |
| 3541 Str << "<null>"; | 3541 Str << "<null>"; |
| 3542 Str << ", Index="; | 3542 Str << ", Index="; |
| 3543 if (Index) | 3543 if (Index) |
| 3544 Index->dump(Func); | 3544 Index->dump(Func); |
| 3545 else | 3545 else |
| 3546 Str << "<null>"; | 3546 Str << "<null>"; |
| 3547 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; | 3547 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; |
| 3548 } | 3548 } |
| 3549 | 3549 |
| 3550 bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) { |
| 3551 // Var originates from Var=SrcVar ==> |
| 3552 // set Var:=SrcVar |
| 3553 if (Var == NULL) |
| 3554 return false; |
| 3555 if (const Inst *VarAssign = Var->getDefinition()) { |
| 3556 if (llvm::isa<InstAssign>(VarAssign)) { |
| 3557 Operand *SrcOp = VarAssign->getSrc(0); |
| 3558 assert(SrcOp); |
| 3559 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
| 3560 if (!SrcVar->getIsMultidef() && |
| 3561 // TODO: ensure SrcVar stays single-BB |
| 3562 true) { |
| 3563 Var = SrcVar; |
| 3564 Reason = VarAssign; |
| 3565 return true; |
| 3566 } |
| 3567 } |
| 3568 } |
| 3569 } |
| 3570 return false; |
| 3571 } |
| 3572 |
| 3573 bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift, |
| 3574 const Inst *&Reason) { |
| 3575 // Index==NULL && Base is Base=Var1+Var2 ==> |
| 3576 // set Base=Var1, Index=Var2, Shift=0 |
| 3577 if (Base == NULL) |
| 3578 return false; |
| 3579 if (Index != NULL) |
| 3580 return false; |
| 3581 const Inst *BaseInst = Base->getDefinition(); |
| 3582 if (BaseInst == NULL) |
| 3583 return false; |
| 3584 if (BaseInst->getSrcSize() < 2) |
| 3585 return false; |
| 3586 if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { |
| 3587 if (Var1->getIsMultidef()) |
| 3588 return false; |
| 3589 if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { |
| 3590 if (Var2->getIsMultidef()) |
| 3591 return false; |
| 3592 if (isAdd(BaseInst) && |
| 3593 // TODO: ensure Var1 and Var2 stay single-BB |
| 3594 true) { |
| 3595 Base = Var1; |
| 3596 Index = Var2; |
| 3597 Shift = 0; // should already have been 0 |
| 3598 Reason = BaseInst; |
| 3599 return true; |
| 3600 } |
| 3601 } |
| 3602 } |
| 3603 return false; |
| 3604 } |
| 3605 |
| 3606 bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) { |
| 3607 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> |
| 3608 // Index=Var, Shift+=log2(Const) |
| 3609 if (Index == NULL) |
| 3610 return false; |
| 3611 const Inst *IndexInst = Index->getDefinition(); |
| 3612 if (IndexInst == NULL) |
| 3613 return false; |
| 3614 if (IndexInst->getSrcSize() < 2) |
| 3615 return false; |
| 3616 if (const InstArithmetic *ArithInst = |
| 3617 llvm::dyn_cast<InstArithmetic>(IndexInst)) { |
| 3618 if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { |
| 3619 if (ConstantInteger *Const = |
| 3620 llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1))) { |
| 3621 if (ArithInst->getOp() == InstArithmetic::Mul && |
| 3622 !Var->getIsMultidef() && Const->getType() == IceType_i32) { |
| 3623 uint64_t Mult = Const->getValue(); |
| 3624 uint32_t LogMult; |
| 3625 switch (Mult) { |
| 3626 case 1: |
| 3627 LogMult = 0; |
| 3628 break; |
| 3629 case 2: |
| 3630 LogMult = 1; |
| 3631 break; |
| 3632 case 4: |
| 3633 LogMult = 2; |
| 3634 break; |
| 3635 case 8: |
| 3636 LogMult = 3; |
| 3637 break; |
| 3638 default: |
| 3639 return false; |
| 3640 } |
| 3641 if (Shift + LogMult <= 3) { |
| 3642 Index = Var; |
| 3643 Shift += LogMult; |
| 3644 Reason = IndexInst; |
| 3645 return true; |
| 3646 } |
| 3647 } |
| 3648 } |
| 3649 } |
| 3650 } |
| 3651 return false; |
| 3652 } |
| 3653 |
| 3654 bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) { |
| 3655 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
| 3656 // set Base=Var, Offset+=Const |
| 3657 // Base is Base=Var-Const ==> |
| 3658 // set Base=Var, Offset-=Const |
| 3659 if (Base == NULL) |
| 3660 return false; |
| 3661 const Inst *BaseInst = Base->getDefinition(); |
| 3662 if (BaseInst == NULL) |
| 3663 return false; |
| 3664 if (const InstArithmetic *ArithInst = |
| 3665 llvm::dyn_cast<const InstArithmetic>(BaseInst)) { |
| 3666 if (ArithInst->getOp() != InstArithmetic::Add && |
| 3667 ArithInst->getOp() != InstArithmetic::Sub) |
| 3668 return false; |
| 3669 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; |
| 3670 Variable *Var = NULL; |
| 3671 ConstantInteger *Const = NULL; |
| 3672 if (Variable *VariableOperand = |
| 3673 llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { |
| 3674 Var = VariableOperand; |
| 3675 Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1)); |
| 3676 } else if (IsAdd) { |
| 3677 Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(0)); |
| 3678 Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); |
| 3679 } |
| 3680 if (Var == NULL || Const == NULL || Var->getIsMultidef()) |
| 3681 return false; |
| 3682 Base = Var; |
| 3683 Offset += IsAdd ? Const->getValue() : -Const->getValue(); |
| 3684 Reason = BaseInst; |
| 3685 return true; |
| 3686 } |
| 3687 return false; |
| 3688 } |
| 3689 |
| 3550 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 3690 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
| 3551 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 3691 Variable *&Index, uint16_t &Shift, int32_t &Offset) { |
| 3552 Func->setCurrentNode(NULL); | 3692 Func->setCurrentNode(NULL); |
| 3553 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { | 3693 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { |
| 3554 Ostream &Str = Func->getContext()->getStrDump(); | 3694 Ostream &Str = Func->getContext()->getStrDump(); |
| 3555 Str << "\nStarting computeAddressOpt for instruction:\n "; | 3695 Str << "\nStarting computeAddressOpt for instruction:\n "; |
| 3556 Instr->dumpDecorated(Func); | 3696 Instr->dumpDecorated(Func); |
| 3557 } | 3697 } |
| 3558 (void)Offset; // TODO: pattern-match for non-zero offsets. | 3698 (void)Offset; // TODO: pattern-match for non-zero offsets. |
| 3559 if (Base == NULL) | 3699 if (Base == NULL) |
| 3560 return; | 3700 return; |
| 3561 // If the Base has more than one use or is live across multiple | 3701 // If the Base has more than one use or is live across multiple |
| 3562 // blocks, then don't go further. Alternatively (?), never consider | 3702 // blocks, then don't go further. Alternatively (?), never consider |
| 3563 // a transformation that would change a variable that is currently | 3703 // a transformation that would change a variable that is currently |
| 3564 // *not* live across basic block boundaries into one that *is*. | 3704 // *not* live across basic block boundaries into one that *is*. |
| 3565 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) | 3705 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) |
| 3566 return; | 3706 return; |
| 3567 | 3707 |
| 3568 while (true) { | 3708 bool Continue = true; |
| 3569 // Base is Base=Var ==> | 3709 while (Continue) { |
| 3570 // set Base=Var | 3710 const Inst *Reason = NULL; |
| 3571 const Inst *BaseInst = Base->getDefinition(); | 3711 if (matchTransitiveAssign(Base, Reason) || |
| 3572 Operand *BaseOperand0 = BaseInst ? BaseInst->getSrc(0) : NULL; | 3712 matchTransitiveAssign(Index, Reason) || |
| 3573 Variable *BaseVariable0 = llvm::dyn_cast_or_null<Variable>(BaseOperand0); | 3713 matchCombinedBaseIndex(Base, Index, Shift, Reason) || |
| 3574 // TODO: Helper function for all instances of assignment | 3714 matchShiftedIndex(Index, Shift, Reason) || |
| 3575 // transitivity. | 3715 matchOffsetBase(Base, Offset, Reason)) { |
| 3576 if (BaseInst && llvm::isa<InstAssign>(BaseInst) && BaseVariable0 && | 3716 dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason); |
| 3577 // TODO: ensure BaseVariable0 stays single-BB | 3717 } else { |
| 3578 true) { | 3718 Continue = false; |
| 3579 Base = BaseVariable0; | |
| 3580 dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst); | |
| 3581 continue; | |
| 3582 } | |
| 3583 | |
| 3584 // Index is Index=Var ==> | |
| 3585 // set Index=Var | |
| 3586 | |
| 3587 // Index==NULL && Base is Base=Var1+Var2 ==> | |
| 3588 // set Base=Var1, Index=Var2, Shift=0 | |
| 3589 Operand *BaseOperand1 = | |
| 3590 BaseInst && BaseInst->getSrcSize() >= 2 ? BaseInst->getSrc(1) : NULL; | |
| 3591 Variable *BaseVariable1 = llvm::dyn_cast_or_null<Variable>(BaseOperand1); | |
| 3592 if (Index == NULL && isAdd(BaseInst) && BaseVariable0 && BaseVariable1 && | |
| 3593 // TODO: ensure BaseVariable0 and BaseVariable1 stay single-BB | |
| 3594 true) { | |
| 3595 Base = BaseVariable0; | |
| 3596 Index = BaseVariable1; | |
| 3597 Shift = 0; // should already have been 0 | |
| 3598 dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst); | |
| 3599 continue; | |
| 3600 } | |
| 3601 | |
| 3602 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> | |
| 3603 // Index=Var, Shift+=log2(Const) | |
| 3604 const Inst *IndexInst = Index ? Index->getDefinition() : NULL; | |
| 3605 if (const InstArithmetic *ArithInst = | |
| 3606 llvm::dyn_cast_or_null<InstArithmetic>(IndexInst)) { | |
| 3607 Operand *IndexOperand0 = ArithInst->getSrc(0); | |
| 3608 Variable *IndexVariable0 = llvm::dyn_cast<Variable>(IndexOperand0); | |
| 3609 Operand *IndexOperand1 = ArithInst->getSrc(1); | |
| 3610 ConstantInteger *IndexConstant1 = | |
| 3611 llvm::dyn_cast<ConstantInteger>(IndexOperand1); | |
| 3612 if (ArithInst->getOp() == InstArithmetic::Mul && IndexVariable0 && | |
| 3613 IndexOperand1->getType() == IceType_i32 && IndexConstant1) { | |
| 3614 uint64_t Mult = IndexConstant1->getValue(); | |
| 3615 uint32_t LogMult; | |
| 3616 switch (Mult) { | |
| 3617 case 1: | |
| 3618 LogMult = 0; | |
| 3619 break; | |
| 3620 case 2: | |
| 3621 LogMult = 1; | |
| 3622 break; | |
| 3623 case 4: | |
| 3624 LogMult = 2; | |
| 3625 break; | |
| 3626 case 8: | |
| 3627 LogMult = 3; | |
| 3628 break; | |
| 3629 default: | |
| 3630 LogMult = 4; | |
| 3631 break; | |
| 3632 } | |
| 3633 if (Shift + LogMult <= 3) { | |
| 3634 Index = IndexVariable0; | |
| 3635 Shift += LogMult; | |
| 3636 dumpAddressOpt(Func, Base, Index, Shift, Offset, IndexInst); | |
| 3637 continue; | |
| 3638 } | |
| 3639 } | |
| 3640 } | |
| 3641 | |
| 3642 // Base is Base=Var+Const || Base is Base=Const+Var ==> | |
| 3643 // set Base=Var, Offset+=Const | |
| 3644 // Base is Base=Var-Const ==> | |
| 3645 // set Base=Var, Offset-=Const | |
| 3646 const InstArithmetic *ArithInst = | |
| 3647 llvm::dyn_cast_or_null<const InstArithmetic>(BaseInst); | |
| 3648 if (ArithInst && (ArithInst->getOp() == InstArithmetic::Add || | |
| 3649 ArithInst->getOp() == InstArithmetic::Sub)) { | |
| 3650 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; | |
| 3651 Variable *Var = NULL; | |
| 3652 ConstantInteger *Const = NULL; | |
| 3653 if (Variable *VariableOperand = | |
| 3654 llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { | |
| 3655 Var = VariableOperand; | |
| 3656 Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1)); | |
| 3657 } else if (IsAdd) { | |
| 3658 Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(0)); | |
| 3659 Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); | |
| 3660 } | |
| 3661 if (!(Const && Var)) { | |
| 3662 break; | |
| 3663 } | |
| 3664 Base = Var; | |
| 3665 Offset += IsAdd ? Const->getValue() : -Const->getValue(); | |
| 3666 dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst); | |
| 3667 continue; | |
| 3668 } | 3719 } |
| 3669 | 3720 |
| 3670 // Index is Index=Var<<Const && Const+Shift<=3 ==> | 3721 // Index is Index=Var<<Const && Const+Shift<=3 ==> |
| 3671 // Index=Var, Shift+=Const | 3722 // Index=Var, Shift+=Const |
| 3672 | 3723 |
| 3673 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> | 3724 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> |
| 3674 // Index=Var, Shift+=log2(Const) | 3725 // Index=Var, Shift+=log2(Const) |
| 3675 | 3726 |
| 3676 // Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> | 3727 // Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> |
| 3677 // swap(Index,Base) | 3728 // swap(Index,Base) |
| 3678 // Similar for Base=Const*Var and Base=Var<<Const | 3729 // Similar for Base=Const*Var and Base=Var<<Const |
| 3679 | 3730 |
| 3680 // Index is Index=Var+Const ==> | 3731 // Index is Index=Var+Const ==> |
| 3681 // set Index=Var, Offset+=(Const<<Shift) | 3732 // set Index=Var, Offset+=(Const<<Shift) |
| 3682 | 3733 |
| 3683 // Index is Index=Const+Var ==> | 3734 // Index is Index=Const+Var ==> |
| 3684 // set Index=Var, Offset+=(Const<<Shift) | 3735 // set Index=Var, Offset+=(Const<<Shift) |
| 3685 | 3736 |
| 3686 // Index is Index=Var-Const ==> | 3737 // Index is Index=Var-Const ==> |
| 3687 // set Index=Var, Offset-=(Const<<Shift) | 3738 // set Index=Var, Offset-=(Const<<Shift) |
| 3688 | 3739 |
| 3689 // TODO: consider overflow issues with respect to Offset. | 3740 // TODO: consider overflow issues with respect to Offset. |
| 3690 // TODO: handle symbolic constants. | 3741 // TODO: handle symbolic constants. |
| 3691 break; | |
| 3692 } | 3742 } |
| 3693 } | 3743 } |
| 3694 | 3744 |
| 3695 } // anonymous namespace | 3745 } // anonymous namespace |
| 3696 | 3746 |
| 3697 void TargetX8632::lowerLoad(const InstLoad *Inst) { | 3747 void TargetX8632::lowerLoad(const InstLoad *Inst) { |
| 3698 // A Load instruction can be treated the same as an Assign | 3748 // A Load instruction can be treated the same as an Assign |
| 3699 // instruction, after the source operand is transformed into an | 3749 // instruction, after the source operand is transformed into an |
| 3700 // OperandX8632Mem operand. Note that the address mode | 3750 // OperandX8632Mem operand. Note that the address mode |
| 3701 // optimization already creates an OperandX8632Mem operand, so it | 3751 // optimization already creates an OperandX8632Mem operand, so it |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4463 Str << "\t.align\t" << Align << "\n"; | 4513 Str << "\t.align\t" << Align << "\n"; |
| 4464 Str << MangledName << ":\n"; | 4514 Str << MangledName << ":\n"; |
| 4465 for (SizeT i = 0; i < Size; ++i) { | 4515 for (SizeT i = 0; i < Size; ++i) { |
| 4466 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; | 4516 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; |
| 4467 } | 4517 } |
| 4468 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 4518 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 4469 } | 4519 } |
| 4470 } | 4520 } |
| 4471 | 4521 |
| 4472 } // end of namespace Ice | 4522 } // end of namespace Ice |
| OLD | NEW |