Chromium Code Reviews| 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 |