OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |