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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | 379 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { |
440 Str << "cl"; | 380 Str << "cl"; |
441 EmittedSrc1 = true; | 381 EmittedSrc1 = true; |
442 } | 382 } |
443 } | 383 } |
444 if (!EmittedSrc1) | 384 if (!EmittedSrc1) |
445 Inst->getSrc(1)->emit(Func); | 385 Inst->getSrc(1)->emit(Func); |
446 Str << "\n"; | 386 Str << "\n"; |
447 } | 387 } |
448 | 388 |
| 389 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { |
| 390 const Variable *Src = llvm::dyn_cast<const Variable>(Source); |
| 391 if (Src == NULL) |
| 392 return false; |
| 393 if (Dest->hasReg() && Dest->getRegNum() == Src->getRegNum()) { |
| 394 // TODO: On x86-64, instructions like "mov eax, eax" are used to |
| 395 // clear the upper 32 bits of rax. We need to recognize and |
| 396 // preserve these. |
| 397 return true; |
| 398 } |
| 399 if (!Dest->hasReg() && !Src->hasReg() && |
| 400 Dest->getStackOffset() == Src->getStackOffset()) |
| 401 return true; |
| 402 return false; |
| 403 } |
449 | 404 |
450 // In-place ops | 405 // In-place ops |
451 template <> const char *InstX8632Bswap::Opcode = "bswap"; | 406 template <> const char *InstX8632Bswap::Opcode = "bswap"; |
452 template <> const char *InstX8632Neg::Opcode = "neg"; | 407 template <> const char *InstX8632Neg::Opcode = "neg"; |
453 // Unary ops | 408 // Unary ops |
454 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 409 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
455 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 410 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
456 template <> const char *InstX8632Lea::Opcode = "lea"; | 411 template <> const char *InstX8632Lea::Opcode = "lea"; |
457 template <> const char *InstX8632Movd::Opcode = "movd"; | 412 template <> const char *InstX8632Movd::Opcode = "movd"; |
458 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | 413 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
459 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; | 414 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
| 415 // Mov-like ops |
| 416 template <> const char *InstX8632Mov::Opcode = "mov"; |
| 417 template <> const char *InstX8632Movp::Opcode = "movups"; |
| 418 template <> const char *InstX8632Movq::Opcode = "movq"; |
460 // Binary ops | 419 // Binary ops |
461 template <> const char *InstX8632Add::Opcode = "add"; | 420 template <> const char *InstX8632Add::Opcode = "add"; |
462 template <> const char *InstX8632Addps::Opcode = "addps"; | 421 template <> const char *InstX8632Addps::Opcode = "addps"; |
463 template <> const char *InstX8632Adc::Opcode = "adc"; | 422 template <> const char *InstX8632Adc::Opcode = "adc"; |
464 template <> const char *InstX8632Addss::Opcode = "addss"; | 423 template <> const char *InstX8632Addss::Opcode = "addss"; |
465 template <> const char *InstX8632Padd::Opcode = "padd"; | 424 template <> const char *InstX8632Padd::Opcode = "padd"; |
466 template <> const char *InstX8632Sub::Opcode = "sub"; | 425 template <> const char *InstX8632Sub::Opcode = "sub"; |
467 template <> const char *InstX8632Subps::Opcode = "subps"; | 426 template <> const char *InstX8632Subps::Opcode = "subps"; |
468 template <> const char *InstX8632Subss::Opcode = "subss"; | 427 template <> const char *InstX8632Subss::Opcode = "subss"; |
469 template <> const char *InstX8632Sbb::Opcode = "sbb"; | 428 template <> const char *InstX8632Sbb::Opcode = "sbb"; |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 Type Ty = VSrc0->getType(); | 951 Type Ty = VSrc0->getType(); |
993 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 952 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
994 // acceptable type. | 953 // acceptable type. |
995 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | 954 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
996 } else { | 955 } else { |
997 Src0->emit(Func); | 956 Src0->emit(Func); |
998 } | 957 } |
999 Str << "\n"; | 958 Str << "\n"; |
1000 } | 959 } |
1001 | 960 |
1002 void InstX8632Mov::emit(const Cfg *Func) const { | 961 template <> void InstX8632Mov::emit(const Cfg *Func) const { |
1003 Ostream &Str = Func->getContext()->getStrEmit(); | 962 Ostream &Str = Func->getContext()->getStrEmit(); |
1004 assert(getSrcSize() == 1); | 963 assert(getSrcSize() == 1); |
1005 Operand *Src = getSrc(0); | 964 Operand *Src = getSrc(0); |
1006 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 965 // The llvm-mc assembler using Intel syntax has a bug in which "mov |
1007 // reg, RelocatableConstant" does not generate the right instruction | 966 // reg, RelocatableConstant" does not generate the right instruction |
1008 // with a relocation. To work around, we emit "lea reg, | 967 // with a relocation. To work around, we emit "lea reg, |
1009 // [RelocatableConstant]". Also, the lowering and legalization is | 968 // [RelocatableConstant]". Also, the lowering and legalization is |
1010 // changed to allow relocatable constants only in Assign and Call | 969 // changed to allow relocatable constants only in Assign and Call |
1011 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | 970 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK |
1012 // once a proper emitter is used. | 971 // 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). | 987 // value between a vector and a scalar (which movss is used for). |
1029 // Clean this up. | 988 // Clean this up. |
1030 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 989 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
1031 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | 990 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); |
1032 getDest()->asType(Src->getType()).emit(Func); | 991 getDest()->asType(Src->getType()).emit(Func); |
1033 Str << ", "; | 992 Str << ", "; |
1034 Src->emit(Func); | 993 Src->emit(Func); |
1035 Str << "\n"; | 994 Str << "\n"; |
1036 } | 995 } |
1037 | 996 |
1038 void InstX8632Mov::dump(const Cfg *Func) const { | 997 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 | 998 // TODO(wala,stichnot): movups works with all vector operands, but |
1048 // there exist other instructions (movaps, movdqa, movdqu) that may | 999 // there exist other instructions (movaps, movdqa, movdqu) that may |
1049 // perform better, depending on the data type and alignment of the | 1000 // perform better, depending on the data type and alignment of the |
1050 // operands. | 1001 // operands. |
1051 Ostream &Str = Func->getContext()->getStrEmit(); | 1002 Ostream &Str = Func->getContext()->getStrEmit(); |
1052 assert(getSrcSize() == 1); | 1003 assert(getSrcSize() == 1); |
1053 Str << "\tmovups\t"; | 1004 Str << "\tmovups\t"; |
1054 getDest()->emit(Func); | 1005 getDest()->emit(Func); |
1055 Str << ", "; | 1006 Str << ", "; |
1056 getSrc(0)->emit(Func); | 1007 getSrc(0)->emit(Func); |
1057 Str << "\n"; | 1008 Str << "\n"; |
1058 } | 1009 } |
1059 | 1010 |
1060 void InstX8632Movp::dump(const Cfg *Func) const { | 1011 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(); | 1012 Ostream &Str = Func->getContext()->getStrEmit(); |
1070 assert(getSrcSize() == 1); | 1013 assert(getSrcSize() == 1); |
1071 assert(getDest()->getType() == IceType_i64 || | 1014 assert(getDest()->getType() == IceType_i64 || |
1072 getDest()->getType() == IceType_f64); | 1015 getDest()->getType() == IceType_f64); |
1073 Str << "\tmovq\t"; | 1016 Str << "\tmovq\t"; |
1074 getDest()->emit(Func); | 1017 getDest()->emit(Func); |
1075 Str << ", "; | 1018 Str << ", "; |
1076 getSrc(0)->emit(Func); | 1019 getSrc(0)->emit(Func); |
1077 Str << "\n"; | 1020 Str << "\n"; |
1078 } | 1021 } |
1079 | 1022 |
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 { | 1023 void InstX8632Movsx::emit(const Cfg *Func) const { |
1089 Ostream &Str = Func->getContext()->getStrEmit(); | 1024 Ostream &Str = Func->getContext()->getStrEmit(); |
1090 assert(getSrcSize() == 1); | 1025 assert(getSrcSize() == 1); |
1091 Str << "\tmovsx\t"; | 1026 Str << "\tmovsx\t"; |
1092 getDest()->emit(Func); | 1027 getDest()->emit(Func); |
1093 Str << ", "; | 1028 Str << ", "; |
1094 getSrc(0)->emit(Func); | 1029 getSrc(0)->emit(Func); |
1095 Str << "\n"; | 1030 Str << "\n"; |
1096 } | 1031 } |
1097 | 1032 |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 default: | 1445 default: |
1511 Str << "???"; | 1446 Str << "???"; |
1512 break; | 1447 break; |
1513 } | 1448 } |
1514 Str << "("; | 1449 Str << "("; |
1515 Var->dump(Func); | 1450 Var->dump(Func); |
1516 Str << ")"; | 1451 Str << ")"; |
1517 } | 1452 } |
1518 | 1453 |
1519 } // end of namespace Ice | 1454 } // end of namespace Ice |
OLD | NEW |