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

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

Powered by Google App Engine
This is Rietveld 408576698