Chromium Code Reviews| Index: src/IceTargetLoweringX86BaseImpl.h |
| diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
| index 49c929b8a5983393e4ddf02cc910c100cb5c6951..a369bd4bdf0df992c772477f30a498af97fb849b 100644 |
| --- a/src/IceTargetLoweringX86BaseImpl.h |
| +++ b/src/IceTargetLoweringX86BaseImpl.h |
| @@ -5270,6 +5270,9 @@ const Inst *AddressOptimizer::matchOffsetIndexOrBase( |
| // set Index=Var, Offset+=(Const<<Shift) |
| // Index is Index=Var-Const ==> |
| // set Index=Var, Offset-=(Const<<Shift) |
| + // Treat Index=Var Or Const as Index=Var + Const |
| + // when Var = Var' << N and log2(Const) <= N |
| + // or when Var = (2^M) * (2^N) and log2(Const) <= (M+N) |
| if (*IndexOrBase == nullptr) { |
| return nullptr; |
| @@ -5280,10 +5283,15 @@ const Inst *AddressOptimizer::matchOffsetIndexOrBase( |
| } |
| assert(!VMetadata->isMultiDef(*IndexOrBase)); |
| if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(Definition)) { |
| - if (ArithInst->getOp() != InstArithmetic::Add && |
| - ArithInst->getOp() != InstArithmetic::Sub) |
| + switch (ArithInst->getOp()) { |
| + case InstArithmetic::Add: |
| + case InstArithmetic::Sub: |
| + case InstArithmetic::Or: |
| + break; |
| + default: |
| return nullptr; |
| - bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; |
| + } |
| + |
| Operand *Src0 = ArithInst->getSrc(0); |
| Operand *Src1 = ArithInst->getSrc(1); |
| auto *Var0 = llvm::dyn_cast<Variable>(Src0); |
| @@ -5292,6 +5300,52 @@ const Inst *AddressOptimizer::matchOffsetIndexOrBase( |
| auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1); |
| auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0); |
| auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1); |
| + |
| + bool IsAdd = false; |
| + if (ArithInst->getOp() == InstArithmetic::Or) { |
| + Variable *Var = nullptr; |
| + ConstantInteger32 *Const = nullptr; |
| + if (Var0 && Const1) { |
| + Var = Var0; |
| + Const = Const1; |
| + } else if (Const0 && Var1) { |
| + Var = Var1; |
| + Const = Const0; |
| + } else |
| + return nullptr; |
|
Jim Stichnoth
2016/06/27 20:33:05
Use braces around the return statement for consist
|
| + |
| + auto *VarDef = |
| + llvm::dyn_cast<InstArithmetic>(VMetadata->getSingleDefinition(Var)); |
| + if (VarDef == nullptr) |
| + return nullptr; |
| + |
| + SizeT ZeroesAvailable = 0; |
| + if (VarDef->getOp() == InstArithmetic::Shl) { |
| + if (auto *ConstInt = |
| + llvm::dyn_cast<ConstantInteger32>(VarDef->getSrc(1))) { |
| + ZeroesAvailable = ConstInt->getValue(); |
| + } |
| + } else if (VarDef->getOp() == InstArithmetic::Mul) { |
| + SizeT PowerOfTwo = 0; |
| + ConstantInteger32 *MultConst = |
| + llvm::dyn_cast<ConstantInteger32>(VarDef->getSrc(0)); |
| + if (llvm::isPowerOf2_32(MultConst->getValue())) { |
| + PowerOfTwo += MultConst->getValue(); |
| + } |
| + MultConst = llvm::dyn_cast<ConstantInteger32>(VarDef->getSrc(1)); |
| + if (llvm::isPowerOf2_32(MultConst->getValue())) { |
| + PowerOfTwo += MultConst->getValue(); |
| + } |
| + ZeroesAvailable = llvm::Log2_32(PowerOfTwo) + 1; |
| + } |
| + SizeT ZeroesNeeded = llvm::Log2_32(Const->getValue()) + 1; |
| + if (ZeroesNeeded == 0 || ZeroesNeeded > ZeroesAvailable) |
| + return nullptr; |
| + IsAdd = true; // treat it as an add if the above conditions hold |
| + } else { |
| + IsAdd = ArithInst->getOp() == InstArithmetic::Add; |
| + } |
| + |
| Variable *NewIndexOrBase = nullptr; |
| int32_t NewOffset = 0; |
| ConstantRelocatable *NewRelocatable = *Relocatable; |
| @@ -5331,7 +5385,7 @@ const Inst *AddressOptimizer::matchOffsetIndexOrBase( |
| NewOffset += MoreOffset; |
| } |
| if (Utils::WouldOverflowAdd(*Offset, NewOffset << Shift)) |
| - return nullptr; |
| + return nullptr; |
| *IndexOrBase = NewIndexOrBase; |
| *Offset += (NewOffset << Shift); |
| // Shift is always zero if this is called with the base |