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

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1428443002: Enhance address mode recovery (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Streamline absolute addressing support (rip-relative on x64) Created 5 years, 1 month 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
OLDNEW
1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==//
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 /// \file 10 /// \file
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 if (Var->mustHaveReg()) { 790 if (Var->mustHaveReg()) {
791 llvm_unreachable("Infinite-weight Variable has no register assigned"); 791 llvm_unreachable("Infinite-weight Variable has no register assigned");
792 } 792 }
793 int32_t Offset = Var->getStackOffset(); 793 int32_t Offset = Var->getStackOffset();
794 int32_t BaseRegNum = Var->getBaseRegNum(); 794 int32_t BaseRegNum = Var->getBaseRegNum();
795 if (Var->getBaseRegNum() == Variable::NoRegister) { 795 if (Var->getBaseRegNum() == Variable::NoRegister) {
796 BaseRegNum = getFrameOrStackReg(); 796 BaseRegNum = getFrameOrStackReg();
797 if (!hasFramePointer()) 797 if (!hasFramePointer())
798 Offset += getStackAdjustment(); 798 Offset += getStackAdjustment();
799 } 799 }
800 static constexpr AssemblerFixup *Fixup = nullptr;
800 return typename Traits::Address( 801 return typename Traits::Address(
801 Traits::RegisterSet::getEncodedGPR(BaseRegNum), Offset); 802 Traits::RegisterSet::getEncodedGPR(BaseRegNum), Offset, Fixup);
802 } 803 }
803 804
804 /// Helper function for addProlog(). 805 /// Helper function for addProlog().
805 /// 806 ///
806 /// This assumes Arg is an argument passed on the stack. This sets the frame 807 /// This assumes Arg is an argument passed on the stack. This sets the frame
807 /// offset for Arg and updates InArgsSizeBytes according to Arg's width. For an 808 /// offset for Arg and updates InArgsSizeBytes according to Arg's width. For an
808 /// I64 arg that has been split into Lo and Hi components, it calls itself 809 /// I64 arg that has been split into Lo and Hi components, it calls itself
809 /// recursively on the components, taking care to handle Lo first because of the 810 /// recursively on the components, taking care to handle Lo first because of the
810 /// little-endian architecture. Lastly, this function generates an instruction 811 /// little-endian architecture. Lastly, this function generates an instruction
811 /// to copy Arg into its assigned register if applicable. 812 /// to copy Arg into its assigned register if applicable.
(...skipping 2032 matching lines...) Expand 10 before | Expand all | Expand 10 after
2844 // Optimize comparisons with zero. 2845 // Optimize comparisons with zero.
2845 if (isZero(Src1)) { 2846 if (isZero(Src1)) {
2846 Constant *SignMask = Ctx->getConstantInt32(0x80000000); 2847 Constant *SignMask = Ctx->getConstantInt32(0x80000000);
2847 Variable *Temp = nullptr; 2848 Variable *Temp = nullptr;
2848 switch (Condition) { 2849 switch (Condition) {
2849 default: 2850 default:
2850 llvm_unreachable("unexpected condition"); 2851 llvm_unreachable("unexpected condition");
2851 break; 2852 break;
2852 case InstIcmp::Eq: 2853 case InstIcmp::Eq:
2853 case InstIcmp::Ule: 2854 case InstIcmp::Ule:
2854 _mov(Temp, Src0LoRM); 2855 // Mov Src0HiRM first, because it was legalized most recently, and will
2855 _or(Temp, Src0HiRM); 2856 // sometimes avoid a move before the OR.
2857 _mov(Temp, Src0HiRM);
2858 _or(Temp, Src0LoRM);
2856 Context.insert(InstFakeUse::create(Func, Temp)); 2859 Context.insert(InstFakeUse::create(Func, Temp));
2857 setccOrBr(Traits::Cond::Br_e, Dest, Br); 2860 setccOrBr(Traits::Cond::Br_e, Dest, Br);
2858 return; 2861 return;
2859 case InstIcmp::Ne: 2862 case InstIcmp::Ne:
2860 case InstIcmp::Ugt: 2863 case InstIcmp::Ugt:
2861 _mov(Temp, Src0LoRM); 2864 // Mov Src0HiRM first, because it was legalized most recently, and will
2862 _or(Temp, Src0HiRM); 2865 // sometimes avoid a move before the OR.
2866 _mov(Temp, Src0HiRM);
2867 _or(Temp, Src0LoRM);
2863 Context.insert(InstFakeUse::create(Func, Temp)); 2868 Context.insert(InstFakeUse::create(Func, Temp));
2864 setccOrBr(Traits::Cond::Br_ne, Dest, Br); 2869 setccOrBr(Traits::Cond::Br_ne, Dest, Br);
2865 return; 2870 return;
2866 case InstIcmp::Uge: 2871 case InstIcmp::Uge:
2867 movOrBr(true, Dest, Br); 2872 movOrBr(true, Dest, Br);
2868 return; 2873 return;
2869 case InstIcmp::Ult: 2874 case InstIcmp::Ult:
2870 movOrBr(false, Dest, Br); 2875 movOrBr(false, Dest, Br);
2871 return; 2876 return;
2872 case InstIcmp::Sgt: 2877 case InstIcmp::Sgt:
(...skipping 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after
4087 const SizeT BundleSize = 4092 const SizeT BundleSize =
4088 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); 4093 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
4089 _and(Target, Ctx->getConstantInt32(~(BundleSize - 1))); 4094 _and(Target, Ctx->getConstantInt32(~(BundleSize - 1)));
4090 } 4095 }
4091 _jmp(Target); 4096 _jmp(Target);
4092 if (NeedSandboxing) 4097 if (NeedSandboxing)
4093 _bundle_unlock(); 4098 _bundle_unlock();
4094 } 4099 }
4095 4100
4096 inline bool isAdd(const Inst *Inst) { 4101 inline bool isAdd(const Inst *Inst) {
4097 if (const InstArithmetic *Arith = 4102 if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
4098 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
4099 return (Arith->getOp() == InstArithmetic::Add); 4103 return (Arith->getOp() == InstArithmetic::Add);
4100 } 4104 }
4101 return false; 4105 return false;
4102 } 4106 }
4103 4107
4104 inline void dumpAddressOpt(const Cfg *Func, const Variable *Base, 4108 inline void dumpAddressOpt(const Cfg *Func,
4109 const ConstantRelocatable *Relocatable,
4110 int32_t Offset, const Variable *Base,
4105 const Variable *Index, uint16_t Shift, 4111 const Variable *Index, uint16_t Shift,
4106 int32_t Offset, const Inst *Reason) { 4112 const Inst *Reason) {
4107 if (!BuildDefs::dump()) 4113 if (!BuildDefs::dump())
4108 return; 4114 return;
4109 if (!Func->isVerbose(IceV_AddrOpt)) 4115 if (!Func->isVerbose(IceV_AddrOpt))
4110 return; 4116 return;
4111 OstreamLocker L(Func->getContext()); 4117 OstreamLocker L(Func->getContext());
4112 Ostream &Str = Func->getContext()->getStrDump(); 4118 Ostream &Str = Func->getContext()->getStrDump();
4113 Str << "Instruction: "; 4119 Str << "Instruction: ";
4114 Reason->dumpDecorated(Func); 4120 Reason->dumpDecorated(Func);
4115 Str << " results in Base="; 4121 Str << " results in Base=";
4116 if (Base) 4122 if (Base)
4117 Base->dump(Func); 4123 Base->dump(Func);
4118 else 4124 else
4119 Str << "<null>"; 4125 Str << "<null>";
4120 Str << ", Index="; 4126 Str << ", Index=";
4121 if (Index) 4127 if (Index)
4122 Index->dump(Func); 4128 Index->dump(Func);
4123 else 4129 else
4124 Str << "<null>"; 4130 Str << "<null>";
4125 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; 4131 Str << ", Shift=" << Shift << ", Offset=" << Offset
4132 << ", Relocatable=" << Relocatable << "\n";
4126 } 4133 }
4127 4134
4128 inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, 4135 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var,
4129 Variable *&Var, const Inst *&Reason) { 4136 ConstantRelocatable *&Relocatable, int32_t &Offset,
4137 const Inst *&Reason) {
4130 // Var originates from Var=SrcVar ==> set Var:=SrcVar 4138 // Var originates from Var=SrcVar ==> set Var:=SrcVar
4131 if (Var == nullptr) 4139 if (Var == nullptr)
4132 return false; 4140 return false;
4133 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { 4141 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) {
4134 assert(!VMetadata->isMultiDef(Var)); 4142 assert(!VMetadata->isMultiDef(Var));
4135 if (llvm::isa<InstAssign>(VarAssign)) { 4143 if (llvm::isa<InstAssign>(VarAssign)) {
4136 Operand *SrcOp = VarAssign->getSrc(0); 4144 Operand *SrcOp = VarAssign->getSrc(0);
4137 assert(SrcOp); 4145 assert(SrcOp);
4138 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { 4146 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
4139 if (!VMetadata->isMultiDef(SrcVar) && 4147 if (!VMetadata->isMultiDef(SrcVar) &&
4140 // TODO: ensure SrcVar stays single-BB 4148 // TODO: ensure SrcVar stays single-BB
4141 true) { 4149 true) {
4142 Var = SrcVar; 4150 Var = SrcVar;
4143 Reason = VarAssign; 4151 Reason = VarAssign;
4144 return true; 4152 return true;
4145 } 4153 }
4154 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
4155 int32_t MoreOffset = Const->getValue();
4156 if (Utils::WouldOverflowAdd(Offset, MoreOffset))
4157 return false;
4158 Var = nullptr;
4159 Offset += MoreOffset;
4160 Reason = VarAssign;
4161 return true;
4162 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) {
4163 if (Relocatable == nullptr) {
4164 Var = nullptr;
4165 Relocatable = AddReloc;
4166 Reason = VarAssign;
4167 return true;
4168 }
4146 } 4169 }
4147 } 4170 }
4148 } 4171 }
4149 return false; 4172 return false;
4150 } 4173 }
4151 4174
4152 inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, 4175 inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata,
4153 Variable *&Base, Variable *&Index, 4176 Variable *&Base, Variable *&Index,
4154 uint16_t &Shift, const Inst *&Reason) { 4177 uint16_t &Shift, const Inst *&Reason) {
4155 // Index==nullptr && Base is Base=Var1+Var2 ==> 4178 // Index==nullptr && Base is Base=Var1+Var2 ==>
4156 // set Base=Var1, Index=Var2, Shift=0 4179 // set Base=Var1, Index=Var2, Shift=0
4157 if (Base == nullptr) 4180 if (Base == nullptr)
4158 return false; 4181 return false;
4159 if (Index != nullptr) 4182 if (Index != nullptr)
4160 return false; 4183 return false;
4161 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); 4184 auto *BaseInst = VMetadata->getSingleDefinition(Base);
4162 if (BaseInst == nullptr) 4185 if (BaseInst == nullptr)
4163 return false; 4186 return false;
4164 assert(!VMetadata->isMultiDef(Base)); 4187 assert(!VMetadata->isMultiDef(Base));
4165 if (BaseInst->getSrcSize() < 2) 4188 if (BaseInst->getSrcSize() < 2)
4166 return false; 4189 return false;
4167 if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { 4190 if (auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
4168 if (VMetadata->isMultiDef(Var1)) 4191 if (VMetadata->isMultiDef(Var1))
4169 return false; 4192 return false;
4170 if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { 4193 if (auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
4171 if (VMetadata->isMultiDef(Var2)) 4194 if (VMetadata->isMultiDef(Var2))
4172 return false; 4195 return false;
4173 if (isAdd(BaseInst) && 4196 if (isAdd(BaseInst) &&
4174 // TODO: ensure Var1 and Var2 stay single-BB 4197 // TODO: ensure Var1 and Var2 stay single-BB
4175 true) { 4198 true) {
4176 Base = Var1; 4199 Base = Var1;
4177 Index = Var2; 4200 Index = Var2;
4178 Shift = 0; // should already have been 0 4201 Shift = 0; // should already have been 0
4179 Reason = BaseInst; 4202 Reason = BaseInst;
4180 return true; 4203 return true;
4181 } 4204 }
4182 } 4205 }
4183 } 4206 }
4184 return false; 4207 return false;
4185 } 4208 }
4186 4209
4187 inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, 4210 inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
4188 Variable *&Index, uint16_t &Shift, 4211 Variable *&Index, uint16_t &Shift,
4189 const Inst *&Reason) { 4212 const Inst *&Reason) {
4190 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> 4213 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
4191 // Index=Var, Shift+=log2(Const) 4214 // Index=Var, Shift+=log2(Const)
4192 if (Index == nullptr) 4215 if (Index == nullptr)
4193 return false; 4216 return false;
4194 const Inst *IndexInst = VMetadata->getSingleDefinition(Index); 4217 auto *IndexInst = VMetadata->getSingleDefinition(Index);
4195 if (IndexInst == nullptr) 4218 if (IndexInst == nullptr)
4196 return false; 4219 return false;
4197 assert(!VMetadata->isMultiDef(Index)); 4220 assert(!VMetadata->isMultiDef(Index));
4198 if (IndexInst->getSrcSize() < 2) 4221 if (IndexInst->getSrcSize() < 2)
4199 return false; 4222 return false;
4200 if (const InstArithmetic *ArithInst = 4223 if (auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst)) {
4201 llvm::dyn_cast<InstArithmetic>(IndexInst)) { 4224 if (auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
4202 if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { 4225 if (auto *Const =
4203 if (ConstantInteger32 *Const =
4204 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { 4226 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
4205 if (ArithInst->getOp() == InstArithmetic::Mul && 4227 if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
4206 !VMetadata->isMultiDef(Var) && Const->getType() == IceType_i32) { 4228 return false;
4207 uint64_t Mult = Const->getValue(); 4229 switch (ArithInst->getOp()) {
4230 default:
4231 return false;
4232 case InstArithmetic::Mul: {
4233 uint32_t Mult = Const->getValue();
4208 uint32_t LogMult; 4234 uint32_t LogMult;
4209 switch (Mult) { 4235 switch (Mult) {
4210 case 1: 4236 case 1:
4211 LogMult = 0; 4237 LogMult = 0;
4212 break; 4238 break;
4213 case 2: 4239 case 2:
4214 LogMult = 1; 4240 LogMult = 1;
4215 break; 4241 break;
4216 case 4: 4242 case 4:
4217 LogMult = 2; 4243 LogMult = 2;
4218 break; 4244 break;
4219 case 8: 4245 case 8:
4220 LogMult = 3; 4246 LogMult = 3;
4221 break; 4247 break;
4222 default: 4248 default:
4223 return false; 4249 return false;
4224 } 4250 }
4225 if (Shift + LogMult <= 3) { 4251 if (Shift + LogMult <= 3) {
4226 Index = Var; 4252 Index = Var;
4227 Shift += LogMult; 4253 Shift += LogMult;
4228 Reason = IndexInst; 4254 Reason = IndexInst;
4229 return true; 4255 return true;
4230 } 4256 }
4231 } 4257 }
4258 case InstArithmetic::Shl: {
4259 uint32_t ShiftAmount = Const->getValue();
4260 switch (ShiftAmount) {
4261 case 0:
4262 case 1:
4263 case 2:
4264 case 3:
4265 break;
4266 default:
4267 return false;
4268 }
4269 if (Shift + ShiftAmount <= 3) {
4270 Index = Var;
4271 Shift += ShiftAmount;
4272 Reason = IndexInst;
4273 return true;
4274 }
4275 }
4276 }
4232 } 4277 }
4233 } 4278 }
4234 } 4279 }
4235 return false; 4280 return false;
4236 } 4281 }
4237 4282
4238 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, 4283 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base,
4239 int32_t &Offset, const Inst *&Reason) { 4284 ConstantRelocatable *&Relocatable, int32_t &Offset,
4285 const Inst *&Reason) {
4240 // Base is Base=Var+Const || Base is Base=Const+Var ==> 4286 // Base is Base=Var+Const || Base is Base=Const+Var ==>
4241 // set Base=Var, Offset+=Const 4287 // set Base=Var, Offset+=Const
4242 // Base is Base=Var-Const ==> 4288 // Base is Base=Var-Const ==>
4243 // set Base=Var, Offset-=Const 4289 // set Base=Var, Offset-=Const
4244 if (Base == nullptr) 4290 if (Base == nullptr) {
4245 return false; 4291 return false;
4292 }
4246 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); 4293 const Inst *BaseInst = VMetadata->getSingleDefinition(Base);
4247 if (BaseInst == nullptr) 4294 if (BaseInst == nullptr) {
4248 return false; 4295 return false;
4296 }
4249 assert(!VMetadata->isMultiDef(Base)); 4297 assert(!VMetadata->isMultiDef(Base));
4250 if (const InstArithmetic *ArithInst = 4298 if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
4251 llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
4252 if (ArithInst->getOp() != InstArithmetic::Add && 4299 if (ArithInst->getOp() != InstArithmetic::Add &&
4253 ArithInst->getOp() != InstArithmetic::Sub) 4300 ArithInst->getOp() != InstArithmetic::Sub)
4254 return false; 4301 return false;
4255 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; 4302 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
4256 Variable *Var = nullptr; 4303 Operand *Src0 = ArithInst->getSrc(0);
4257 ConstantInteger32 *Const = nullptr; 4304 Operand *Src1 = ArithInst->getSrc(1);
4258 if (Variable *VariableOperand = 4305 auto *Var0 = llvm::dyn_cast<Variable>(Src0);
4259 llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { 4306 auto *Var1 = llvm::dyn_cast<Variable>(Src1);
4260 Var = VariableOperand; 4307 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
4261 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1)); 4308 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
4262 } else if (IsAdd) { 4309 auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0);
4263 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0)); 4310 auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1);
4264 Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); 4311 Variable *NewBase = nullptr;
4312 int32_t NewOffset = Offset;
4313 ConstantRelocatable *NewRelocatable = Relocatable;
4314 if (Var0 && Var1)
4315 // TODO(sehr): merge base/index splitting into here.
4316 return false;
4317 else if (!IsAdd && Var1)
Jim Stichnoth 2015/10/27 22:19:52 Don't use "else" after "if (...) return;". (here a
sehr 2015/10/27 23:24:05 Done.
4318 return false;
4319 else if (Var0)
4320 NewBase = Var0;
4321 else if (Var1)
4322 NewBase = Var1;
4323 // Don't know how to add/subtract two relocatables.
4324 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
4325 return false;
4326 // Don't know how to subtract a relocatable.
4327 if (!IsAdd && Reloc1)
4328 return false;
4329 // Incorporate ConstantRelocatables.
4330 if (Reloc0)
4331 NewRelocatable = Reloc0;
4332 else if (Reloc1)
4333 NewRelocatable = Reloc1;
4334 // Compute the updated constant offset.
4335 if (Const0) {
4336 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
4337 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4338 return false;
4339 NewOffset += MoreOffset;
4265 } 4340 }
4266 if (Var == nullptr || Const == nullptr || VMetadata->isMultiDef(Var)) 4341 if (Const1) {
4267 return false; 4342 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
4268 int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue(); 4343 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4269 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) 4344 return false;
4270 return false; 4345 NewOffset += MoreOffset;
4271 Base = Var; 4346 }
4272 Offset += MoreOffset; 4347 // Update the computed address parameters once we are sure optimization
4348 // is valid.
4349 Base = NewBase;
4350 Offset = NewOffset;
4351 Relocatable = NewRelocatable;
4273 Reason = BaseInst; 4352 Reason = BaseInst;
4274 return true; 4353 return true;
4275 } 4354 }
4276 return false; 4355 return false;
4277 } 4356 }
4278 4357
4279 inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, 4358 // Builds information for a canonical address expresion:
4280 Variable *&Index, uint16_t &Shift, 4359 // <Relocatable + Offset>(Base, Index, Shift)
4281 int32_t &Offset) { 4360 // On entry:
4361 // Relocatable == null,
4362 // Offset == 0,
4363 // Base is a Variable,
4364 // Index == nullptr,
4365 // Shift == 0
4366 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr,
4367 ConstantRelocatable *&Relocatable,
4368 int32_t &Offset, Variable *&Base,
4369 Variable *&Index, uint16_t &Shift) {
4370 bool AddressWasOptimized = false;
4282 Func->resetCurrentNode(); 4371 Func->resetCurrentNode();
4283 if (Func->isVerbose(IceV_AddrOpt)) { 4372 if (Func->isVerbose(IceV_AddrOpt)) {
4284 OstreamLocker L(Func->getContext()); 4373 OstreamLocker L(Func->getContext());
4285 Ostream &Str = Func->getContext()->getStrDump(); 4374 Ostream &Str = Func->getContext()->getStrDump();
4286 Str << "\nStarting computeAddressOpt for instruction:\n "; 4375 Str << "\nStarting computeAddressOpt for instruction:\n ";
4287 Instr->dumpDecorated(Func); 4376 Instr->dumpDecorated(Func);
4288 } 4377 }
4289 (void)Offset; // TODO: pattern-match for non-zero offsets.
4290 if (Base == nullptr) 4378 if (Base == nullptr)
4291 return; 4379 return AddressWasOptimized;
4292 // If the Base has more than one use or is live across multiple blocks, then 4380 // If the Base has more than one use or is live across multiple blocks, then
4293 // don't go further. Alternatively (?), never consider a transformation that 4381 // don't go further. Alternatively (?), never consider a transformation that
4294 // would change a variable that is currently *not* live across basic block 4382 // would change a variable that is currently *not* live across basic block
4295 // boundaries into one that *is*. 4383 // boundaries into one that *is*.
4296 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/) 4384 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
4297 return; 4385 return AddressWasOptimized;
4298 4386
4299 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); 4387 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
4300 const VariablesMetadata *VMetadata = Func->getVMetadata(); 4388 const VariablesMetadata *VMetadata = Func->getVMetadata();
4301 bool Continue = true; 4389 const Inst *Reason = nullptr;
4302 while (Continue) { 4390 do {
4303 const Inst *Reason = nullptr; 4391 if (Reason) {
4304 if (matchTransitiveAssign(VMetadata, Base, Reason) || 4392 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason);
4305 matchTransitiveAssign(VMetadata, Index, Reason) || 4393 AddressWasOptimized = true;
4306 (!MockBounds && 4394 Reason = nullptr;
4307 matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) ||
4308 (!MockBounds && matchShiftedIndex(VMetadata, Index, Shift, Reason)) ||
4309 matchOffsetBase(VMetadata, Base, Offset, Reason)) {
4310 dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason);
4311 } else {
4312 Continue = false;
4313 } 4395 }
4396 // Update Base and Index to follow through assignments to definitions.
4397 if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) {
4398 // Assignments of Base from a Relocatable or ConstantInt32 can result
4399 // in Base becoming nullptr. To avoid code duplication in this loop we
4400 // prefer that Base be non-nullptr if possible.
4401 if ((Base == nullptr) && (Index != nullptr) && (Shift == 0))
4402 std::swap(Base, Index);
4403 continue;
4404 }
4405 if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason))
4406 continue;
4314 4407
4315 // Index is Index=Var<<Const && Const+Shift<=3 ==> 4408 if (!MockBounds) {
4316 // Index=Var, Shift+=Const 4409 // Transition from:
4317 4410 // <Relocatable + Offset>(Base) to
4318 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> 4411 // <Relocatable + Offset>(Base, Index)
4319 // Index=Var, Shift+=log2(Const) 4412 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason))
4320 4413 continue;
4321 // Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> 4414 // Recognize multiply/shift and update Shift amount.
4322 // swap(Index,Base) 4415 // Index becomes Index=Var<<Const && Const+Shift<=3 ==>
4323 // Similar for Base=Const*Var and Base=Var<<Const 4416 // Index=Var, Shift+=Const
4324 4417 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
4418 // Index=Var, Shift+=log2(Const)
4419 if (matchShiftedIndex(VMetadata, Index, Shift, Reason))
4420 continue;
4421 // If Shift is zero, the choice of Base and Index was purely arbitrary.
4422 // Recognize multiply/shift and set Shift amount.
4423 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
4424 // swap(Index,Base)
4425 // Similar for Base=Const*Var and Base=Var<<Const
4426 if ((Shift == 0) && matchShiftedIndex(VMetadata, Base, Shift, Reason)) {
4427 std::swap(Base, Index);
4428 continue;
4429 }
4430 }
4431 // Update Offset to reflect additions/subtractions with constants and
4432 // relocatables.
4433 // TODO: consider overflow issues with respect to Offset.
4434 // TODO: handle symbolic constants.
4435 if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason))
4436 continue;
4437 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0.
4325 // Index is Index=Var+Const ==> 4438 // Index is Index=Var+Const ==>
4326 // set Index=Var, Offset+=(Const<<Shift) 4439 // set Index=Var, Offset+=(Const<<Shift)
4327
4328 // Index is Index=Const+Var ==> 4440 // Index is Index=Const+Var ==>
4329 // set Index=Var, Offset+=(Const<<Shift) 4441 // set Index=Var, Offset+=(Const<<Shift)
4330
4331 // Index is Index=Var-Const ==> 4442 // Index is Index=Var-Const ==>
4332 // set Index=Var, Offset-=(Const<<Shift) 4443 // set Index=Var, Offset-=(Const<<Shift)
4333 4444 break;
4334 // TODO: consider overflow issues with respect to Offset. 4445 } while (Reason);
4335 // TODO: handle symbolic constants. 4446 return AddressWasOptimized;
4336 }
4337 } 4447 }
4338 4448
4339 /// Add a mock bounds check on the memory address before using it as a load or 4449 /// Add a mock bounds check on the memory address before using it as a load or
4340 /// store operand. The basic idea is that given a memory operand [reg], we 4450 /// store operand. The basic idea is that given a memory operand [reg], we
4341 /// would first add bounds-check code something like: 4451 /// would first add bounds-check code something like:
4342 /// 4452 ///
4343 /// cmp reg, <lb> 4453 /// cmp reg, <lb>
4344 /// jl out_of_line_error 4454 /// jl out_of_line_error
4345 /// cmp reg, <ub> 4455 /// cmp reg, <ub>
4346 /// jg out_of_line_error 4456 /// jg out_of_line_error
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4408 doMockBoundsCheck(Src0); 4518 doMockBoundsCheck(Src0);
4409 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); 4519 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0);
4410 lowerAssign(Assign); 4520 lowerAssign(Assign);
4411 } 4521 }
4412 4522
4413 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { 4523 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() {
4414 Inst *Inst = Context.getCur(); 4524 Inst *Inst = Context.getCur();
4415 Variable *Dest = Inst->getDest(); 4525 Variable *Dest = Inst->getDest();
4416 Operand *Addr = Inst->getSrc(0); 4526 Operand *Addr = Inst->getSrc(0);
4417 Variable *Index = nullptr; 4527 Variable *Index = nullptr;
4528 ConstantRelocatable *Relocatable = nullptr;
4418 uint16_t Shift = 0; 4529 uint16_t Shift = 0;
4419 int32_t Offset = 0; // TODO: make Constant 4530 int32_t Offset = 0;
4420 // Vanilla ICE load instructions should not use the segment registers, and 4531 // Vanilla ICE load instructions should not use the segment registers, and
4421 // computeAddressOpt only works at the level of Variables and Constants, not 4532 // computeAddressOpt only works at the level of Variables and Constants, not
4422 // other Traits::X86OperandMem, so there should be no mention of segment 4533 // other Traits::X86OperandMem, so there should be no mention of segment
4423 // registers there either. 4534 // registers there either.
4424 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = 4535 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg =
4425 Traits::X86OperandMem::DefaultSegment; 4536 Traits::X86OperandMem::DefaultSegment;
4426 Variable *Base = llvm::dyn_cast<Variable>(Addr); 4537 auto *Base = llvm::dyn_cast<Variable>(Addr);
4427 computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); 4538 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) {
4428 if (Base && Addr != Base) {
4429 Inst->setDeleted(); 4539 Inst->setDeleted();
4430 Constant *OffsetOp = Ctx->getConstantInt32(Offset); 4540 Constant *OffsetOp = nullptr;
4541 if (Relocatable == nullptr) {
4542 OffsetOp = Ctx->getConstantInt32(Offset);
4543 } else {
4544 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
4545 Relocatable->getName(),
4546 Relocatable->getSuppressMangling());
4547 }
4431 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, 4548 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp,
4432 Index, Shift, SegmentReg); 4549 Index, Shift, SegmentReg);
4433 Context.insert(InstLoad::create(Func, Dest, Addr)); 4550 Context.insert(InstLoad::create(Func, Dest, Addr));
4434 } 4551 }
4435 } 4552 }
4436 4553
4437 template <class Machine> 4554 template <class Machine>
4438 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, 4555 void TargetX86Base<Machine>::randomlyInsertNop(float Probability,
4439 RandomNumberGenerator &RNG) { 4556 RandomNumberGenerator &RNG) {
4440 RandomNumberGeneratorWrapper RNGW(RNG); 4557 RandomNumberGeneratorWrapper RNGW(RNG);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
4616 Value = legalize(Value, Legal_Reg | Legal_Imm); 4733 Value = legalize(Value, Legal_Reg | Legal_Imm);
4617 _store(Value, NewAddr); 4734 _store(Value, NewAddr);
4618 } 4735 }
4619 } 4736 }
4620 4737
4621 template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { 4738 template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() {
4622 InstStore *Inst = llvm::cast<InstStore>(Context.getCur()); 4739 InstStore *Inst = llvm::cast<InstStore>(Context.getCur());
4623 Operand *Data = Inst->getData(); 4740 Operand *Data = Inst->getData();
4624 Operand *Addr = Inst->getAddr(); 4741 Operand *Addr = Inst->getAddr();
4625 Variable *Index = nullptr; 4742 Variable *Index = nullptr;
4743 ConstantRelocatable *Relocatable = nullptr;
4626 uint16_t Shift = 0; 4744 uint16_t Shift = 0;
4627 int32_t Offset = 0; // TODO: make Constant 4745 int32_t Offset = 0;
4628 Variable *Base = llvm::dyn_cast<Variable>(Addr); 4746 auto *Base = llvm::dyn_cast<Variable>(Addr);
4629 // Vanilla ICE store instructions should not use the segment registers, and 4747 // Vanilla ICE store instructions should not use the segment registers, and
4630 // computeAddressOpt only works at the level of Variables and Constants, not 4748 // computeAddressOpt only works at the level of Variables and Constants, not
4631 // other Traits::X86OperandMem, so there should be no mention of segment 4749 // other Traits::X86OperandMem, so there should be no mention of segment
4632 // registers there either. 4750 // registers there either.
4633 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = 4751 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg =
4634 Traits::X86OperandMem::DefaultSegment; 4752 Traits::X86OperandMem::DefaultSegment;
4635 computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); 4753 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) {
4636 if (Base && Addr != Base) {
4637 Inst->setDeleted(); 4754 Inst->setDeleted();
4638 Constant *OffsetOp = Ctx->getConstantInt32(Offset); 4755 Constant *OffsetOp = nullptr;
4756 if (Relocatable == nullptr) {
4757 OffsetOp = Ctx->getConstantInt32(Offset);
4758 } else {
4759 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
4760 Relocatable->getName(),
4761 Relocatable->getSuppressMangling());
4762 }
4639 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, 4763 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp,
4640 Index, Shift, SegmentReg); 4764 Index, Shift, SegmentReg);
4641 InstStore *NewStore = InstStore::create(Func, Data, Addr); 4765 InstStore *NewStore = InstStore::create(Func, Data, Addr);
4642 if (Inst->getDest()) 4766 if (Inst->getDest())
4643 NewStore->setRmwBeacon(Inst->getRmwBeacon()); 4767 NewStore->setRmwBeacon(Inst->getRmwBeacon());
4644 Context.insert(NewStore); 4768 Context.insert(NewStore);
4645 } 4769 }
4646 } 4770 }
4647 4771
4648 template <class Machine> 4772 template <class Machine>
(...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after
5641 } 5765 }
5642 // the offset is not eligible for blinding or pooling, return the original 5766 // the offset is not eligible for blinding or pooling, return the original
5643 // mem operand 5767 // mem operand
5644 return MemOperand; 5768 return MemOperand;
5645 } 5769 }
5646 5770
5647 } // end of namespace X86Internal 5771 } // end of namespace X86Internal
5648 } // end of namespace Ice 5772 } // end of namespace Ice
5649 5773
5650 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H 5774 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698