OLD | NEW |
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
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 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 : InstX8632(Func, InstX8632::Mfence, 0, NULL) { | 212 : InstX8632(Func, InstX8632::Mfence, 0, NULL) { |
213 HasSideEffects = true; | 213 HasSideEffects = true; |
214 } | 214 } |
215 | 215 |
216 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) | 216 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
217 : InstX8632(Func, InstX8632::Store, 2, NULL) { | 217 : InstX8632(Func, InstX8632::Store, 2, NULL) { |
218 addSource(Value); | 218 addSource(Value); |
219 addSource(Mem); | 219 addSource(Mem); |
220 } | 220 } |
221 | 221 |
222 InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
223 : InstX8632(Func, InstX8632::Mov, 1, Dest) { | |
224 addSource(Source); | |
225 } | |
226 | |
227 InstX8632Movp::InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source) | |
228 : InstX8632(Func, InstX8632::Movp, 1, Dest) { | |
229 addSource(Source); | |
230 } | |
231 | |
232 InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem) | 222 InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
233 : InstX8632(Func, InstX8632::StoreP, 2, NULL) { | 223 : InstX8632(Func, InstX8632::StoreP, 2, NULL) { |
234 addSource(Value); | 224 addSource(Value); |
235 addSource(Mem); | 225 addSource(Mem); |
236 } | 226 } |
237 | 227 |
238 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem) | 228 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
239 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) { | 229 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) { |
240 addSource(Value); | 230 addSource(Value); |
241 addSource(Mem); | 231 addSource(Mem); |
242 } | 232 } |
243 | 233 |
244 InstX8632Movq::InstX8632Movq(Cfg *Func, Variable *Dest, Operand *Source) | |
245 : InstX8632(Func, InstX8632::Movq, 1, Dest) { | |
246 addSource(Source); | |
247 } | |
248 | |
249 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) | 234 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) |
250 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { | 235 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { |
251 addSource(Source); | 236 addSource(Source); |
252 } | 237 } |
253 | 238 |
254 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) | 239 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) |
255 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { | 240 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { |
256 addSource(Source); | 241 addSource(Source); |
257 } | 242 } |
258 | 243 |
259 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) | 244 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) |
260 : InstX8632(Func, InstX8632::Fld, 1, NULL) { | 245 : InstX8632(Func, InstX8632::Fld, 1, NULL) { |
261 addSource(Src); | 246 addSource(Src); |
262 } | 247 } |
263 | 248 |
264 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) | 249 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) |
265 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} | 250 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} |
266 | 251 |
267 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) | 252 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) |
268 : InstX8632(Func, InstX8632::Pop, 0, Dest) {} | 253 : InstX8632(Func, InstX8632::Pop, 0, Dest) {} |
269 | 254 |
270 InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, | 255 InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, |
271 bool SuppressStackAdjustment) | 256 bool SuppressStackAdjustment) |
272 : InstX8632(Func, InstX8632::Push, 1, NULL), | 257 : InstX8632(Func, InstX8632::Push, 1, NULL), |
273 SuppressStackAdjustment(SuppressStackAdjustment) { | 258 SuppressStackAdjustment(SuppressStackAdjustment) { |
274 addSource(Source); | 259 addSource(Source); |
275 } | 260 } |
276 | 261 |
277 bool InstX8632Mov::isRedundantAssign() const { | |
278 // TODO(stichnot): The isRedundantAssign() implementations for | |
279 // InstX8632Mov, InstX8632Movp, and InstX8632Movq are | |
280 // identical. Consolidate them. | |
281 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); | |
282 if (Src == NULL) | |
283 return false; | |
284 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { | |
285 // TODO: On x86-64, instructions like "mov eax, eax" are used to | |
286 // clear the upper 32 bits of rax. We need to recognize and | |
287 // preserve these. | |
288 return true; | |
289 } | |
290 if (!getDest()->hasReg() && !Src->hasReg() && | |
291 Dest->getStackOffset() == Src->getStackOffset()) | |
292 return true; | |
293 return false; | |
294 } | |
295 | |
296 bool InstX8632Movp::isRedundantAssign() const { | |
297 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); | |
298 if (Src == NULL) | |
299 return false; | |
300 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { | |
301 return true; | |
302 } | |
303 if (!getDest()->hasReg() && !Src->hasReg() && | |
304 Dest->getStackOffset() == Src->getStackOffset()) | |
305 return true; | |
306 return false; | |
307 } | |
308 | |
309 bool InstX8632Movq::isRedundantAssign() const { | |
310 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); | |
311 if (Src == NULL) | |
312 return false; | |
313 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { | |
314 return true; | |
315 } | |
316 if (!getDest()->hasReg() && !Src->hasReg() && | |
317 Dest->getStackOffset() == Src->getStackOffset()) | |
318 return true; | |
319 return false; | |
320 } | |
321 | |
322 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) | 262 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) |
323 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { | 263 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { |
324 if (Source) | 264 if (Source) |
325 addSource(Source); | 265 addSource(Source); |
326 } | 266 } |
327 | 267 |
328 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, | 268 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, |
329 bool Locked) | 269 bool Locked) |
330 : InstX8632Lockable(Func, InstX8632::Xadd, 2, | 270 : InstX8632Lockable(Func, InstX8632::Xadd, 2, |
331 llvm::dyn_cast<Variable>(Dest), Locked) { | 271 llvm::dyn_cast<Variable>(Dest), Locked) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 // In-place ops | 390 // In-place ops |
451 template <> const char *InstX8632Bswap::Opcode = "bswap"; | 391 template <> const char *InstX8632Bswap::Opcode = "bswap"; |
452 template <> const char *InstX8632Neg::Opcode = "neg"; | 392 template <> const char *InstX8632Neg::Opcode = "neg"; |
453 // Unary ops | 393 // Unary ops |
454 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 394 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
455 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 395 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
456 template <> const char *InstX8632Lea::Opcode = "lea"; | 396 template <> const char *InstX8632Lea::Opcode = "lea"; |
457 template <> const char *InstX8632Movd::Opcode = "movd"; | 397 template <> const char *InstX8632Movd::Opcode = "movd"; |
458 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | 398 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
459 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; | 399 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
| 400 // Mov-like ops |
| 401 template <> const char *InstX8632Mov::Opcode = "mov"; |
| 402 template <> const char *InstX8632Movp::Opcode = "movups"; |
| 403 template <> const char *InstX8632Movq::Opcode = "movq"; |
460 // Binary ops | 404 // Binary ops |
461 template <> const char *InstX8632Add::Opcode = "add"; | 405 template <> const char *InstX8632Add::Opcode = "add"; |
462 template <> const char *InstX8632Addps::Opcode = "addps"; | 406 template <> const char *InstX8632Addps::Opcode = "addps"; |
463 template <> const char *InstX8632Adc::Opcode = "adc"; | 407 template <> const char *InstX8632Adc::Opcode = "adc"; |
464 template <> const char *InstX8632Addss::Opcode = "addss"; | 408 template <> const char *InstX8632Addss::Opcode = "addss"; |
465 template <> const char *InstX8632Padd::Opcode = "padd"; | 409 template <> const char *InstX8632Padd::Opcode = "padd"; |
466 template <> const char *InstX8632Sub::Opcode = "sub"; | 410 template <> const char *InstX8632Sub::Opcode = "sub"; |
467 template <> const char *InstX8632Subps::Opcode = "subps"; | 411 template <> const char *InstX8632Subps::Opcode = "subps"; |
468 template <> const char *InstX8632Subss::Opcode = "subss"; | 412 template <> const char *InstX8632Subss::Opcode = "subss"; |
469 template <> const char *InstX8632Sbb::Opcode = "sbb"; | 413 template <> const char *InstX8632Sbb::Opcode = "sbb"; |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 Type Ty = VSrc0->getType(); | 936 Type Ty = VSrc0->getType(); |
993 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 937 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
994 // acceptable type. | 938 // acceptable type. |
995 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | 939 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
996 } else { | 940 } else { |
997 Src0->emit(Func); | 941 Src0->emit(Func); |
998 } | 942 } |
999 Str << "\n"; | 943 Str << "\n"; |
1000 } | 944 } |
1001 | 945 |
1002 void InstX8632Mov::emit(const Cfg *Func) const { | 946 template <> void InstX8632Mov::emit(const Cfg *Func) const { |
1003 Ostream &Str = Func->getContext()->getStrEmit(); | 947 Ostream &Str = Func->getContext()->getStrEmit(); |
1004 assert(getSrcSize() == 1); | 948 assert(getSrcSize() == 1); |
1005 Operand *Src = getSrc(0); | 949 Operand *Src = getSrc(0); |
1006 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 950 // The llvm-mc assembler using Intel syntax has a bug in which "mov |
1007 // reg, RelocatableConstant" does not generate the right instruction | 951 // reg, RelocatableConstant" does not generate the right instruction |
1008 // with a relocation. To work around, we emit "lea reg, | 952 // with a relocation. To work around, we emit "lea reg, |
1009 // [RelocatableConstant]". Also, the lowering and legalization is | 953 // [RelocatableConstant]". Also, the lowering and legalization is |
1010 // changed to allow relocatable constants only in Assign and Call | 954 // changed to allow relocatable constants only in Assign and Call |
1011 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | 955 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK |
1012 // once a proper emitter is used. | 956 // once a proper emitter is used. |
(...skipping 15 matching lines...) Expand all Loading... |
1028 // value between a vector and a scalar (which movss is used for). | 972 // value between a vector and a scalar (which movss is used for). |
1029 // Clean this up. | 973 // Clean this up. |
1030 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 974 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
1031 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | 975 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); |
1032 getDest()->asType(Src->getType()).emit(Func); | 976 getDest()->asType(Src->getType()).emit(Func); |
1033 Str << ", "; | 977 Str << ", "; |
1034 Src->emit(Func); | 978 Src->emit(Func); |
1035 Str << "\n"; | 979 Str << "\n"; |
1036 } | 980 } |
1037 | 981 |
1038 void InstX8632Mov::dump(const Cfg *Func) const { | 982 template <> void InstX8632Movp::emit(const Cfg *Func) const { |
1039 Ostream &Str = Func->getContext()->getStrDump(); | |
1040 Str << "mov." << getDest()->getType() << " "; | |
1041 dumpDest(Func); | |
1042 Str << ", "; | |
1043 dumpSources(Func); | |
1044 } | |
1045 | |
1046 void InstX8632Movp::emit(const Cfg *Func) const { | |
1047 // TODO(wala,stichnot): movups works with all vector operands, but | 983 // TODO(wala,stichnot): movups works with all vector operands, but |
1048 // there exist other instructions (movaps, movdqa, movdqu) that may | 984 // there exist other instructions (movaps, movdqa, movdqu) that may |
1049 // perform better, depending on the data type and alignment of the | 985 // perform better, depending on the data type and alignment of the |
1050 // operands. | 986 // operands. |
1051 Ostream &Str = Func->getContext()->getStrEmit(); | 987 Ostream &Str = Func->getContext()->getStrEmit(); |
1052 assert(getSrcSize() == 1); | 988 assert(getSrcSize() == 1); |
1053 Str << "\tmovups\t"; | 989 Str << "\tmovups\t"; |
1054 getDest()->emit(Func); | 990 getDest()->emit(Func); |
1055 Str << ", "; | 991 Str << ", "; |
1056 getSrc(0)->emit(Func); | 992 getSrc(0)->emit(Func); |
1057 Str << "\n"; | 993 Str << "\n"; |
1058 } | 994 } |
1059 | 995 |
1060 void InstX8632Movp::dump(const Cfg *Func) const { | 996 template <> void InstX8632Movq::emit(const Cfg *Func) const { |
1061 Ostream &Str = Func->getContext()->getStrDump(); | |
1062 Str << "movups." << getDest()->getType() << " "; | |
1063 dumpDest(Func); | |
1064 Str << ", "; | |
1065 dumpSources(Func); | |
1066 } | |
1067 | |
1068 void InstX8632Movq::emit(const Cfg *Func) const { | |
1069 Ostream &Str = Func->getContext()->getStrEmit(); | 997 Ostream &Str = Func->getContext()->getStrEmit(); |
1070 assert(getSrcSize() == 1); | 998 assert(getSrcSize() == 1); |
1071 assert(getDest()->getType() == IceType_i64 || | 999 assert(getDest()->getType() == IceType_i64 || |
1072 getDest()->getType() == IceType_f64); | 1000 getDest()->getType() == IceType_f64); |
1073 Str << "\tmovq\t"; | 1001 Str << "\tmovq\t"; |
1074 getDest()->emit(Func); | 1002 getDest()->emit(Func); |
1075 Str << ", "; | 1003 Str << ", "; |
1076 getSrc(0)->emit(Func); | 1004 getSrc(0)->emit(Func); |
1077 Str << "\n"; | 1005 Str << "\n"; |
1078 } | 1006 } |
1079 | 1007 |
1080 void InstX8632Movq::dump(const Cfg *Func) const { | |
1081 Ostream &Str = Func->getContext()->getStrDump(); | |
1082 Str << "movq." << getDest()->getType() << " "; | |
1083 dumpDest(Func); | |
1084 Str << ", "; | |
1085 dumpSources(Func); | |
1086 } | |
1087 | |
1088 void InstX8632Movsx::emit(const Cfg *Func) const { | 1008 void InstX8632Movsx::emit(const Cfg *Func) const { |
1089 Ostream &Str = Func->getContext()->getStrEmit(); | 1009 Ostream &Str = Func->getContext()->getStrEmit(); |
1090 assert(getSrcSize() == 1); | 1010 assert(getSrcSize() == 1); |
1091 Str << "\tmovsx\t"; | 1011 Str << "\tmovsx\t"; |
1092 getDest()->emit(Func); | 1012 getDest()->emit(Func); |
1093 Str << ", "; | 1013 Str << ", "; |
1094 getSrc(0)->emit(Func); | 1014 getSrc(0)->emit(Func); |
1095 Str << "\n"; | 1015 Str << "\n"; |
1096 } | 1016 } |
1097 | 1017 |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 default: | 1430 default: |
1511 Str << "???"; | 1431 Str << "???"; |
1512 break; | 1432 break; |
1513 } | 1433 } |
1514 Str << "("; | 1434 Str << "("; |
1515 Var->dump(Func); | 1435 Var->dump(Func); |
1516 Str << ")"; | 1436 Str << ")"; |
1517 } | 1437 } |
1518 | 1438 |
1519 } // end of namespace Ice | 1439 } // end of namespace Ice |
OLD | NEW |