| Index: src/IceTargetLoweringX8632.cpp
|
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
|
| index 0beb311e56e0ef690701a6fbb1125dbd14ccd3d0..ec0dc3fbde9727ab525d0704691df34df228519c 100644
|
| --- a/src/IceTargetLoweringX8632.cpp
|
| +++ b/src/IceTargetLoweringX8632.cpp
|
| @@ -3547,6 +3547,146 @@ void dumpAddressOpt(const Cfg *Func, const Variable *Base,
|
| Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n";
|
| }
|
|
|
| +bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) {
|
| + // Var originates from Var=SrcVar ==>
|
| + // set Var:=SrcVar
|
| + if (Var == NULL)
|
| + return false;
|
| + if (const Inst *VarAssign = Var->getDefinition()) {
|
| + if (llvm::isa<InstAssign>(VarAssign)) {
|
| + Operand *SrcOp = VarAssign->getSrc(0);
|
| + assert(SrcOp);
|
| + if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
|
| + if (!SrcVar->getIsMultidef() &&
|
| + // TODO: ensure SrcVar stays single-BB
|
| + true) {
|
| + Var = SrcVar;
|
| + Reason = VarAssign;
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift,
|
| + const Inst *&Reason) {
|
| + // Index==NULL && Base is Base=Var1+Var2 ==>
|
| + // set Base=Var1, Index=Var2, Shift=0
|
| + if (Base == NULL)
|
| + return false;
|
| + if (Index != NULL)
|
| + return false;
|
| + const Inst *BaseInst = Base->getDefinition();
|
| + if (BaseInst == NULL)
|
| + return false;
|
| + if (BaseInst->getSrcSize() < 2)
|
| + return false;
|
| + if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
|
| + if (Var1->getIsMultidef())
|
| + return false;
|
| + if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
|
| + if (Var2->getIsMultidef())
|
| + return false;
|
| + if (isAdd(BaseInst) &&
|
| + // TODO: ensure Var1 and Var2 stay single-BB
|
| + true) {
|
| + Base = Var1;
|
| + Index = Var2;
|
| + Shift = 0; // should already have been 0
|
| + Reason = BaseInst;
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) {
|
| + // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
|
| + // Index=Var, Shift+=log2(Const)
|
| + if (Index == NULL)
|
| + return false;
|
| + const Inst *IndexInst = Index->getDefinition();
|
| + if (IndexInst == NULL)
|
| + return false;
|
| + if (IndexInst->getSrcSize() < 2)
|
| + return false;
|
| + if (const InstArithmetic *ArithInst =
|
| + llvm::dyn_cast<InstArithmetic>(IndexInst)) {
|
| + if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
|
| + if (ConstantInteger *Const =
|
| + llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1))) {
|
| + if (ArithInst->getOp() == InstArithmetic::Mul &&
|
| + !Var->getIsMultidef() && Const->getType() == IceType_i32) {
|
| + uint64_t Mult = Const->getValue();
|
| + uint32_t LogMult;
|
| + switch (Mult) {
|
| + case 1:
|
| + LogMult = 0;
|
| + break;
|
| + case 2:
|
| + LogMult = 1;
|
| + break;
|
| + case 4:
|
| + LogMult = 2;
|
| + break;
|
| + case 8:
|
| + LogMult = 3;
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| + if (Shift + LogMult <= 3) {
|
| + Index = Var;
|
| + Shift += LogMult;
|
| + Reason = IndexInst;
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) {
|
| + // Base is Base=Var+Const || Base is Base=Const+Var ==>
|
| + // set Base=Var, Offset+=Const
|
| + // Base is Base=Var-Const ==>
|
| + // set Base=Var, Offset-=Const
|
| + if (Base == NULL)
|
| + return false;
|
| + const Inst *BaseInst = Base->getDefinition();
|
| + if (BaseInst == NULL)
|
| + return false;
|
| + if (const InstArithmetic *ArithInst =
|
| + llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
|
| + if (ArithInst->getOp() != InstArithmetic::Add &&
|
| + ArithInst->getOp() != InstArithmetic::Sub)
|
| + return false;
|
| + bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
|
| + Variable *Var = NULL;
|
| + ConstantInteger *Const = NULL;
|
| + if (Variable *VariableOperand =
|
| + llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
|
| + Var = VariableOperand;
|
| + Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1));
|
| + } else if (IsAdd) {
|
| + Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(0));
|
| + Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1));
|
| + }
|
| + if (Var == NULL || Const == NULL || Var->getIsMultidef())
|
| + return false;
|
| + Base = Var;
|
| + Offset += IsAdd ? Const->getValue() : -Const->getValue();
|
| + Reason = BaseInst;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
|
| Variable *&Index, uint16_t &Shift, int32_t &Offset) {
|
| Func->setCurrentNode(NULL);
|
| @@ -3565,106 +3705,17 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
|
| if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/)
|
| return;
|
|
|
| - while (true) {
|
| - // Base is Base=Var ==>
|
| - // set Base=Var
|
| - const Inst *BaseInst = Base->getDefinition();
|
| - Operand *BaseOperand0 = BaseInst ? BaseInst->getSrc(0) : NULL;
|
| - Variable *BaseVariable0 = llvm::dyn_cast_or_null<Variable>(BaseOperand0);
|
| - // TODO: Helper function for all instances of assignment
|
| - // transitivity.
|
| - if (BaseInst && llvm::isa<InstAssign>(BaseInst) && BaseVariable0 &&
|
| - // TODO: ensure BaseVariable0 stays single-BB
|
| - true) {
|
| - Base = BaseVariable0;
|
| - dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst);
|
| - continue;
|
| - }
|
| -
|
| - // Index is Index=Var ==>
|
| - // set Index=Var
|
| -
|
| - // Index==NULL && Base is Base=Var1+Var2 ==>
|
| - // set Base=Var1, Index=Var2, Shift=0
|
| - Operand *BaseOperand1 =
|
| - BaseInst && BaseInst->getSrcSize() >= 2 ? BaseInst->getSrc(1) : NULL;
|
| - Variable *BaseVariable1 = llvm::dyn_cast_or_null<Variable>(BaseOperand1);
|
| - if (Index == NULL && isAdd(BaseInst) && BaseVariable0 && BaseVariable1 &&
|
| - // TODO: ensure BaseVariable0 and BaseVariable1 stay single-BB
|
| - true) {
|
| - Base = BaseVariable0;
|
| - Index = BaseVariable1;
|
| - Shift = 0; // should already have been 0
|
| - dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst);
|
| - continue;
|
| - }
|
| -
|
| - // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
|
| - // Index=Var, Shift+=log2(Const)
|
| - const Inst *IndexInst = Index ? Index->getDefinition() : NULL;
|
| - if (const InstArithmetic *ArithInst =
|
| - llvm::dyn_cast_or_null<InstArithmetic>(IndexInst)) {
|
| - Operand *IndexOperand0 = ArithInst->getSrc(0);
|
| - Variable *IndexVariable0 = llvm::dyn_cast<Variable>(IndexOperand0);
|
| - Operand *IndexOperand1 = ArithInst->getSrc(1);
|
| - ConstantInteger *IndexConstant1 =
|
| - llvm::dyn_cast<ConstantInteger>(IndexOperand1);
|
| - if (ArithInst->getOp() == InstArithmetic::Mul && IndexVariable0 &&
|
| - IndexOperand1->getType() == IceType_i32 && IndexConstant1) {
|
| - uint64_t Mult = IndexConstant1->getValue();
|
| - uint32_t LogMult;
|
| - switch (Mult) {
|
| - case 1:
|
| - LogMult = 0;
|
| - break;
|
| - case 2:
|
| - LogMult = 1;
|
| - break;
|
| - case 4:
|
| - LogMult = 2;
|
| - break;
|
| - case 8:
|
| - LogMult = 3;
|
| - break;
|
| - default:
|
| - LogMult = 4;
|
| - break;
|
| - }
|
| - if (Shift + LogMult <= 3) {
|
| - Index = IndexVariable0;
|
| - Shift += LogMult;
|
| - dumpAddressOpt(Func, Base, Index, Shift, Offset, IndexInst);
|
| - continue;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Base is Base=Var+Const || Base is Base=Const+Var ==>
|
| - // set Base=Var, Offset+=Const
|
| - // Base is Base=Var-Const ==>
|
| - // set Base=Var, Offset-=Const
|
| - const InstArithmetic *ArithInst =
|
| - llvm::dyn_cast_or_null<const InstArithmetic>(BaseInst);
|
| - if (ArithInst && (ArithInst->getOp() == InstArithmetic::Add ||
|
| - ArithInst->getOp() == InstArithmetic::Sub)) {
|
| - bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
|
| - Variable *Var = NULL;
|
| - ConstantInteger *Const = NULL;
|
| - if (Variable *VariableOperand =
|
| - llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
|
| - Var = VariableOperand;
|
| - Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(1));
|
| - } else if (IsAdd) {
|
| - Const = llvm::dyn_cast<ConstantInteger>(ArithInst->getSrc(0));
|
| - Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1));
|
| - }
|
| - if (!(Const && Var)) {
|
| - break;
|
| - }
|
| - Base = Var;
|
| - Offset += IsAdd ? Const->getValue() : -Const->getValue();
|
| - dumpAddressOpt(Func, Base, Index, Shift, Offset, BaseInst);
|
| - continue;
|
| + bool Continue = true;
|
| + while (Continue) {
|
| + const Inst *Reason = NULL;
|
| + if (matchTransitiveAssign(Base, Reason) ||
|
| + matchTransitiveAssign(Index, Reason) ||
|
| + matchCombinedBaseIndex(Base, Index, Shift, Reason) ||
|
| + matchShiftedIndex(Index, Shift, Reason) ||
|
| + matchOffsetBase(Base, Offset, Reason)) {
|
| + dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason);
|
| + } else {
|
| + Continue = false;
|
| }
|
|
|
| // Index is Index=Var<<Const && Const+Shift<=3 ==>
|
| @@ -3688,7 +3739,6 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
|
|
|
| // TODO: consider overflow issues with respect to Offset.
|
| // TODO: handle symbolic constants.
|
| - break;
|
| }
|
| }
|
|
|
|
|