OLD | NEW |
1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- 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 // This file declares the InstARM32 and OperandARM32 classes and | 10 // This file declares the InstARM32 and OperandARM32 classes and |
11 // their subclasses. This represents the machine instructions and | 11 // their subclasses. This represents the machine instructions and |
12 // operands used for ARM32 code selection. | 12 // operands used for ARM32 code selection. |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #ifndef SUBZERO_SRC_ICEINSTARM32_H | 16 #ifndef SUBZERO_SRC_ICEINSTARM32_H |
17 #define SUBZERO_SRC_ICEINSTARM32_H | 17 #define SUBZERO_SRC_ICEINSTARM32_H |
18 | 18 |
| 19 #include "IceConditionCodesARM32.h" |
19 #include "IceDefs.h" | 20 #include "IceDefs.h" |
20 #include "IceInst.h" | 21 #include "IceInst.h" |
21 #include "IceInstARM32.def" | 22 #include "IceInstARM32.def" |
22 #include "IceOperand.h" | 23 #include "IceOperand.h" |
23 | 24 |
24 namespace Ice { | 25 namespace Ice { |
25 | 26 |
26 class TargetARM32; | 27 class TargetARM32; |
27 | 28 |
28 // OperandARM32 extends the Operand hierarchy. Its subclasses are | 29 // OperandARM32 extends the Operand hierarchy. Its subclasses are |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 private: | 231 private: |
231 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, | 232 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, |
232 Operand *ShiftAmt); | 233 Operand *ShiftAmt); |
233 ~OperandARM32FlexReg() override {} | 234 ~OperandARM32FlexReg() override {} |
234 | 235 |
235 Variable *Reg; | 236 Variable *Reg; |
236 ShiftKind ShiftOp; | 237 ShiftKind ShiftOp; |
237 Operand *ShiftAmt; | 238 Operand *ShiftAmt; |
238 }; | 239 }; |
239 | 240 |
| 241 // Base class for ARM instructions. While most ARM instructions can be |
| 242 // conditionally executed, a few of them are not predicable (halt, |
| 243 // memory barriers, etc.). |
240 class InstARM32 : public InstTarget { | 244 class InstARM32 : public InstTarget { |
241 InstARM32() = delete; | 245 InstARM32() = delete; |
242 InstARM32(const InstARM32 &) = delete; | 246 InstARM32(const InstARM32 &) = delete; |
243 InstARM32 &operator=(const InstARM32 &) = delete; | 247 InstARM32 &operator=(const InstARM32 &) = delete; |
244 | 248 |
245 public: | 249 public: |
246 enum InstKindARM32 { | 250 enum InstKindARM32 { |
247 k__Start = Inst::Target, | 251 k__Start = Inst::Target, |
248 Adc, | 252 Adc, |
249 Add, | 253 Add, |
250 And, | 254 And, |
| 255 Br, |
| 256 Call, |
| 257 Cmp, |
251 Eor, | 258 Eor, |
252 Ldr, | 259 Ldr, |
| 260 Lsl, |
253 Mla, | 261 Mla, |
254 Mov, | 262 Mov, |
255 Movt, | 263 Movt, |
256 Movw, | 264 Movw, |
257 Mul, | 265 Mul, |
258 Mvn, | 266 Mvn, |
259 Orr, | 267 Orr, |
260 Ret, | 268 Ret, |
261 Sbc, | 269 Sbc, |
262 Sub, | 270 Sub, |
263 Umull | 271 Umull |
264 }; | 272 }; |
265 | 273 |
266 static const char *getWidthString(Type Ty); | 274 static const char *getWidthString(Type Ty); |
| 275 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); |
267 | 276 |
268 void dump(const Cfg *Func) const override; | 277 void dump(const Cfg *Func) const override; |
269 | 278 |
270 protected: | 279 protected: |
271 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) | 280 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) |
272 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 281 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
273 ~InstARM32() override {} | 282 ~InstARM32() override {} |
274 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { | 283 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { |
275 return Inst->getKind() == static_cast<InstKind>(MyKind); | 284 return Inst->getKind() == static_cast<InstKind>(MyKind); |
276 } | 285 } |
277 }; | 286 }; |
278 | 287 |
279 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func); | 288 // A predicable ARM instruction. |
280 void emitThreeAddr(const char *Opcode, const Inst *Inst, const Cfg *Func, | 289 class InstARM32Pred : public InstARM32 { |
281 bool SetFlags); | 290 InstARM32Pred() = delete; |
| 291 InstARM32Pred(const InstARM32Pred &) = delete; |
| 292 InstARM32Pred &operator=(const InstARM32Pred &) = delete; |
282 | 293 |
283 // TODO(jvoung): add condition codes if instruction can be predicated. | 294 public: |
| 295 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, |
| 296 CondARM32::Cond Predicate) |
| 297 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} |
| 298 |
| 299 CondARM32::Cond getPredicate() const { return Predicate; } |
| 300 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } |
| 301 |
| 302 static const char *predString(CondARM32::Cond Predicate); |
| 303 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; |
| 304 |
| 305 // Shared emit routines for common forms of instructions. |
| 306 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 307 const Cfg *Func); |
| 308 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 309 const Cfg *Func, bool SetFlags); |
| 310 |
| 311 protected: |
| 312 CondARM32::Cond Predicate; |
| 313 }; |
| 314 |
| 315 template <typename StreamType> |
| 316 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { |
| 317 Stream << InstARM32Pred::predString(Predicate); |
| 318 return Stream; |
| 319 } |
284 | 320 |
285 // Instructions of the form x := op(y). | 321 // Instructions of the form x := op(y). |
286 template <InstARM32::InstKindARM32 K> | 322 template <InstARM32::InstKindARM32 K> |
287 class InstARM32UnaryopGPR : public InstARM32 { | 323 class InstARM32UnaryopGPR : public InstARM32Pred { |
288 InstARM32UnaryopGPR() = delete; | 324 InstARM32UnaryopGPR() = delete; |
289 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; | 325 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; |
290 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; | 326 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; |
291 | 327 |
292 public: | 328 public: |
293 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 329 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, |
| 330 CondARM32::Cond Predicate) { |
294 return new (Func->allocate<InstARM32UnaryopGPR>()) | 331 return new (Func->allocate<InstARM32UnaryopGPR>()) |
295 InstARM32UnaryopGPR(Func, Dest, Src); | 332 InstARM32UnaryopGPR(Func, Dest, Src, Predicate); |
296 } | 333 } |
297 void emit(const Cfg *Func) const override { | 334 void emit(const Cfg *Func) const override { |
298 if (!ALLOW_DUMP) | 335 if (!ALLOW_DUMP) |
299 return; | 336 return; |
300 Ostream &Str = Func->getContext()->getStrEmit(); | 337 Ostream &Str = Func->getContext()->getStrEmit(); |
301 assert(getSrcSize() == 1); | 338 assert(getSrcSize() == 1); |
302 Str << "\t" << Opcode << "\t"; | 339 Str << "\t" << Opcode << "\t"; |
303 getDest()->emit(Func); | 340 getDest()->emit(Func); |
304 Str << ", "; | 341 Str << ", "; |
305 getSrc(0)->emit(Func); | 342 getSrc(0)->emit(Func); |
306 } | 343 } |
307 void emitIAS(const Cfg *Func) const override { | 344 void emitIAS(const Cfg *Func) const override { |
308 (void)Func; | 345 (void)Func; |
309 llvm_unreachable("Not yet implemented"); | 346 llvm_unreachable("Not yet implemented"); |
310 } | 347 } |
311 void dump(const Cfg *Func) const override { | 348 void dump(const Cfg *Func) const override { |
312 if (!ALLOW_DUMP) | 349 if (!ALLOW_DUMP) |
313 return; | 350 return; |
314 Ostream &Str = Func->getContext()->getStrDump(); | 351 Ostream &Str = Func->getContext()->getStrDump(); |
315 dumpDest(Func); | 352 dumpDest(Func); |
316 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 353 Str << " = "; |
| 354 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 355 Str << " "; |
317 dumpSources(Func); | 356 dumpSources(Func); |
318 } | 357 } |
319 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 358 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
320 | 359 |
321 private: | 360 private: |
322 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 361 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, |
323 : InstARM32(Func, K, 1, Dest) { | 362 CondARM32::Cond Predicate) |
| 363 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
324 addSource(Src); | 364 addSource(Src); |
325 } | 365 } |
326 ~InstARM32UnaryopGPR() override {} | 366 ~InstARM32UnaryopGPR() override {} |
327 static const char *Opcode; | 367 static const char *Opcode; |
328 }; | 368 }; |
329 | 369 |
330 // Instructions of the form x := x op y. | 370 // Instructions of the form x := x op y. |
331 template <InstARM32::InstKindARM32 K> | 371 template <InstARM32::InstKindARM32 K> |
332 class InstARM32TwoAddrGPR : public InstARM32 { | 372 class InstARM32TwoAddrGPR : public InstARM32Pred { |
333 InstARM32TwoAddrGPR() = delete; | 373 InstARM32TwoAddrGPR() = delete; |
334 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; | 374 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; |
335 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; | 375 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; |
336 | 376 |
337 public: | 377 public: |
338 // Dest must be a register. | 378 // Dest must be a register. |
339 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 379 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, |
| 380 CondARM32::Cond Predicate) { |
340 return new (Func->allocate<InstARM32TwoAddrGPR>()) | 381 return new (Func->allocate<InstARM32TwoAddrGPR>()) |
341 InstARM32TwoAddrGPR(Func, Dest, Src); | 382 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); |
342 } | 383 } |
343 void emit(const Cfg *Func) const override { | 384 void emit(const Cfg *Func) const override { |
344 if (!ALLOW_DUMP) | 385 if (!ALLOW_DUMP) |
345 return; | 386 return; |
346 emitTwoAddr(Opcode, this, Func); | 387 emitTwoAddr(Opcode, this, Func); |
347 } | 388 } |
348 void emitIAS(const Cfg *Func) const override { | 389 void emitIAS(const Cfg *Func) const override { |
349 (void)Func; | 390 (void)Func; |
350 llvm::report_fatal_error("Not yet implemented"); | 391 llvm::report_fatal_error("Not yet implemented"); |
351 } | 392 } |
352 void dump(const Cfg *Func) const override { | 393 void dump(const Cfg *Func) const override { |
353 if (!ALLOW_DUMP) | 394 if (!ALLOW_DUMP) |
354 return; | 395 return; |
355 Ostream &Str = Func->getContext()->getStrDump(); | 396 Ostream &Str = Func->getContext()->getStrDump(); |
356 dumpDest(Func); | 397 dumpDest(Func); |
357 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 398 Str << " = "; |
| 399 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 400 Str << " "; |
358 dumpSources(Func); | 401 dumpSources(Func); |
359 } | 402 } |
360 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 403 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
361 | 404 |
362 private: | 405 private: |
363 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src) | 406 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, |
364 : InstARM32(Func, K, 2, Dest) { | 407 CondARM32::Cond Predicate) |
| 408 : InstARM32Pred(Func, K, 2, Dest, Predicate) { |
365 addSource(Dest); | 409 addSource(Dest); |
366 addSource(Src); | 410 addSource(Src); |
367 } | 411 } |
368 ~InstARM32TwoAddrGPR() override {} | 412 ~InstARM32TwoAddrGPR() override {} |
369 static const char *Opcode; | 413 static const char *Opcode; |
370 }; | 414 }; |
371 | 415 |
372 // Base class for assignment instructions. | 416 // Base class for assignment instructions. |
373 // These can be tested for redundancy (and elided if redundant). | 417 // These can be tested for redundancy (and elided if redundant). |
374 template <InstARM32::InstKindARM32 K> | 418 template <InstARM32::InstKindARM32 K> |
375 class InstARM32Movlike : public InstARM32 { | 419 class InstARM32Movlike : public InstARM32Pred { |
376 InstARM32Movlike() = delete; | 420 InstARM32Movlike() = delete; |
377 InstARM32Movlike(const InstARM32Movlike &) = delete; | 421 InstARM32Movlike(const InstARM32Movlike &) = delete; |
378 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; | 422 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; |
379 | 423 |
380 public: | 424 public: |
381 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) { | 425 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 426 CondARM32::Cond Predicate) { |
382 return new (Func->allocate<InstARM32Movlike>()) | 427 return new (Func->allocate<InstARM32Movlike>()) |
383 InstARM32Movlike(Func, Dest, Source); | 428 InstARM32Movlike(Func, Dest, Source, Predicate); |
384 } | 429 } |
385 bool isRedundantAssign() const override { | 430 bool isRedundantAssign() const override { |
386 return checkForRedundantAssign(getDest(), getSrc(0)); | 431 return checkForRedundantAssign(getDest(), getSrc(0)); |
387 } | 432 } |
388 bool isSimpleAssign() const override { return true; } | 433 bool isSimpleAssign() const override { return true; } |
389 void emit(const Cfg *Func) const override; | 434 void emit(const Cfg *Func) const override; |
390 void emitIAS(const Cfg *Func) const override; | 435 void emitIAS(const Cfg *Func) const override; |
391 void dump(const Cfg *Func) const override { | 436 void dump(const Cfg *Func) const override { |
392 if (!ALLOW_DUMP) | 437 if (!ALLOW_DUMP) |
393 return; | 438 return; |
394 Ostream &Str = Func->getContext()->getStrDump(); | 439 Ostream &Str = Func->getContext()->getStrDump(); |
395 Str << Opcode << "." << getDest()->getType() << " "; | 440 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 441 Str << " "; |
396 dumpDest(Func); | 442 dumpDest(Func); |
397 Str << ", "; | 443 Str << ", "; |
398 dumpSources(Func); | 444 dumpSources(Func); |
399 } | 445 } |
400 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 446 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
401 | 447 |
402 private: | 448 private: |
403 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source) | 449 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, |
404 : InstARM32(Func, K, 1, Dest) { | 450 CondARM32::Cond Predicate) |
| 451 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
405 addSource(Source); | 452 addSource(Source); |
406 } | 453 } |
407 ~InstARM32Movlike() override {} | 454 ~InstARM32Movlike() override {} |
408 | 455 |
409 static const char *Opcode; | 456 static const char *Opcode; |
410 }; | 457 }; |
411 | 458 |
412 // Instructions of the form x := y op z. May have the side-effect of setting | 459 // Instructions of the form x := y op z. May have the side-effect of setting |
413 // status flags. | 460 // status flags. |
414 template <InstARM32::InstKindARM32 K> | 461 template <InstARM32::InstKindARM32 K> |
415 class InstARM32ThreeAddrGPR : public InstARM32 { | 462 class InstARM32ThreeAddrGPR : public InstARM32Pred { |
416 InstARM32ThreeAddrGPR() = delete; | 463 InstARM32ThreeAddrGPR() = delete; |
417 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; | 464 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; |
418 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; | 465 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; |
419 | 466 |
420 public: | 467 public: |
421 // Create an ordinary binary-op instruction like add, and sub. | 468 // Create an ordinary binary-op instruction like add, and sub. |
422 // Dest and Src1 must be registers. | 469 // Dest and Src1 must be registers. |
423 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, | 470 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, |
424 Variable *Src1, Operand *Src2, | 471 Variable *Src1, Operand *Src2, |
| 472 CondARM32::Cond Predicate, |
425 bool SetFlags = false) { | 473 bool SetFlags = false) { |
426 return new (Func->allocate<InstARM32ThreeAddrGPR>()) | 474 return new (Func->allocate<InstARM32ThreeAddrGPR>()) |
427 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, SetFlags); | 475 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, Predicate, SetFlags); |
428 } | 476 } |
429 void emit(const Cfg *Func) const override { | 477 void emit(const Cfg *Func) const override { |
430 if (!ALLOW_DUMP) | 478 if (!ALLOW_DUMP) |
431 return; | 479 return; |
432 emitThreeAddr(Opcode, this, Func, SetFlags); | 480 emitThreeAddr(Opcode, this, Func, SetFlags); |
433 } | 481 } |
434 void emitIAS(const Cfg *Func) const override { | 482 void emitIAS(const Cfg *Func) const override { |
435 (void)Func; | 483 (void)Func; |
436 llvm::report_fatal_error("Not yet implemented"); | 484 llvm::report_fatal_error("Not yet implemented"); |
437 } | 485 } |
438 void dump(const Cfg *Func) const override { | 486 void dump(const Cfg *Func) const override { |
439 if (!ALLOW_DUMP) | 487 if (!ALLOW_DUMP) |
440 return; | 488 return; |
441 Ostream &Str = Func->getContext()->getStrDump(); | 489 Ostream &Str = Func->getContext()->getStrDump(); |
442 dumpDest(Func); | 490 dumpDest(Func); |
443 Str << " = " << Opcode << (SetFlags ? "s" : "") << "." | 491 Str << " = "; |
444 << getDest()->getType() << " "; | 492 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 493 Str << (SetFlags ? ".s " : " "); |
445 dumpSources(Func); | 494 dumpSources(Func); |
446 } | 495 } |
447 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 496 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
448 | 497 |
449 private: | 498 private: |
450 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, | 499 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, |
451 Operand *Src2, bool SetFlags) | 500 Operand *Src2, CondARM32::Cond Predicate, bool SetFlags) |
452 : InstARM32(Func, K, 2, Dest), SetFlags(SetFlags) { | 501 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { |
453 addSource(Src1); | 502 addSource(Src1); |
454 addSource(Src2); | 503 addSource(Src2); |
455 } | 504 } |
456 ~InstARM32ThreeAddrGPR() override {} | 505 ~InstARM32ThreeAddrGPR() override {} |
457 static const char *Opcode; | 506 static const char *Opcode; |
458 bool SetFlags; | 507 bool SetFlags; |
459 }; | 508 }; |
460 | 509 |
461 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; | 510 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; |
462 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; | 511 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; |
463 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; | 512 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; |
464 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; | 513 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; |
| 514 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; |
465 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; | 515 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; |
466 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; | 516 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; |
467 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; | 517 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; |
468 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; | 518 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; |
469 // Move instruction (variable <- flex). This is more of a pseudo-inst. | 519 // Move instruction (variable <- flex). This is more of a pseudo-inst. |
470 // If var is a register, then we use "mov". If var is stack, then we use | 520 // If var is a register, then we use "mov". If var is stack, then we use |
471 // "str" to store to the stack. | 521 // "str" to store to the stack. |
472 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; | 522 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; |
473 // MovT leaves the bottom bits alone so dest is also a source. | 523 // MovT leaves the bottom bits alone so dest is also a source. |
474 // This helps indicate that a previous MovW setting dest is not dead code. | 524 // This helps indicate that a previous MovW setting dest is not dead code. |
475 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; | 525 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; |
476 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; | 526 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; |
477 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; | 527 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; |
478 | 528 |
| 529 // Direct branch instruction. |
| 530 class InstARM32Br : public InstARM32Pred { |
| 531 InstARM32Br() = delete; |
| 532 InstARM32Br(const InstARM32Br &) = delete; |
| 533 InstARM32Br &operator=(const InstARM32Br &) = delete; |
| 534 |
| 535 public: |
| 536 // Create a conditional branch to one of two nodes. |
| 537 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, |
| 538 CfgNode *TargetFalse, CondARM32::Cond Predicate) { |
| 539 assert(Predicate != CondARM32::AL); |
| 540 return new (Func->allocate<InstARM32Br>()) |
| 541 InstARM32Br(Func, TargetTrue, TargetFalse, Predicate); |
| 542 } |
| 543 // Create an unconditional branch to a node. |
| 544 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { |
| 545 const CfgNode *NoCondTarget = nullptr; |
| 546 return new (Func->allocate<InstARM32Br>()) |
| 547 InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL); |
| 548 } |
| 549 // Create a non-terminator conditional branch to a node, with a |
| 550 // fallthrough to the next instruction in the current node. This is |
| 551 // used for switch lowering. |
| 552 static InstARM32Br *create(Cfg *Func, CfgNode *Target, |
| 553 CondARM32::Cond Predicate) { |
| 554 assert(Predicate != CondARM32::AL); |
| 555 const CfgNode *NoUncondTarget = nullptr; |
| 556 return new (Func->allocate<InstARM32Br>()) |
| 557 InstARM32Br(Func, Target, NoUncondTarget, Predicate); |
| 558 } |
| 559 const CfgNode *getTargetTrue() const { return TargetTrue; } |
| 560 const CfgNode *getTargetFalse() const { return TargetFalse; } |
| 561 bool optimizeBranch(const CfgNode *NextNode); |
| 562 uint32_t getEmitInstCount() const override { |
| 563 uint32_t Sum = 0; |
| 564 if (getTargetTrue()) |
| 565 ++Sum; |
| 566 if (getTargetFalse()) |
| 567 ++Sum; |
| 568 return Sum; |
| 569 } |
| 570 bool isUnconditionalBranch() const override { |
| 571 return getPredicate() == CondARM32::AL; |
| 572 } |
| 573 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |
| 574 void emit(const Cfg *Func) const override; |
| 575 void emitIAS(const Cfg *Func) const override; |
| 576 void dump(const Cfg *Func) const override; |
| 577 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |
| 578 |
| 579 private: |
| 580 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 581 CondARM32::Cond Predicate); |
| 582 ~InstARM32Br() override {} |
| 583 const CfgNode *TargetTrue; |
| 584 const CfgNode *TargetFalse; |
| 585 }; |
| 586 |
| 587 // Call instruction (bl/blx). Arguments should have already been pushed. |
| 588 // Technically bl and the register form of blx can be predicated, but we'll |
| 589 // leave that out until needed. |
| 590 class InstARM32Call : public InstARM32 { |
| 591 InstARM32Call() = delete; |
| 592 InstARM32Call(const InstARM32Call &) = delete; |
| 593 InstARM32Call &operator=(const InstARM32Call &) = delete; |
| 594 |
| 595 public: |
| 596 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |
| 597 return new (Func->allocate<InstARM32Call>()) |
| 598 InstARM32Call(Func, Dest, CallTarget); |
| 599 } |
| 600 Operand *getCallTarget() const { return getSrc(0); } |
| 601 void emit(const Cfg *Func) const override; |
| 602 void emitIAS(const Cfg *Func) const override; |
| 603 void dump(const Cfg *Func) const override; |
| 604 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
| 605 |
| 606 private: |
| 607 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
| 608 ~InstARM32Call() override {} |
| 609 }; |
| 610 |
| 611 // Integer compare instruction. |
| 612 class InstARM32Cmp : public InstARM32Pred { |
| 613 InstARM32Cmp() = delete; |
| 614 InstARM32Cmp(const InstARM32Cmp &) = delete; |
| 615 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; |
| 616 |
| 617 public: |
| 618 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, |
| 619 CondARM32::Cond Predicate) { |
| 620 return new (Func->allocate<InstARM32Cmp>()) |
| 621 InstARM32Cmp(Func, Src1, Src2, Predicate); |
| 622 } |
| 623 void emit(const Cfg *Func) const override; |
| 624 void emitIAS(const Cfg *Func) const override; |
| 625 void dump(const Cfg *Func) const override; |
| 626 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } |
| 627 |
| 628 private: |
| 629 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, |
| 630 CondARM32::Cond Predicate); |
| 631 ~InstARM32Cmp() override {} |
| 632 }; |
| 633 |
479 // Load instruction. | 634 // Load instruction. |
480 class InstARM32Ldr : public InstARM32 { | 635 class InstARM32Ldr : public InstARM32Pred { |
481 InstARM32Ldr() = delete; | 636 InstARM32Ldr() = delete; |
482 InstARM32Ldr(const InstARM32Ldr &) = delete; | 637 InstARM32Ldr(const InstARM32Ldr &) = delete; |
483 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; | 638 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; |
484 | 639 |
485 public: | 640 public: |
486 // Dest must be a register. | 641 // Dest must be a register. |
487 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem) { | 642 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
488 return new (Func->allocate<InstARM32Ldr>()) InstARM32Ldr(Func, Dest, Mem); | 643 CondARM32::Cond Predicate) { |
| 644 return new (Func->allocate<InstARM32Ldr>()) |
| 645 InstARM32Ldr(Func, Dest, Mem, Predicate); |
489 } | 646 } |
490 void emit(const Cfg *Func) const override; | 647 void emit(const Cfg *Func) const override; |
491 void emitIAS(const Cfg *Func) const override; | 648 void emitIAS(const Cfg *Func) const override; |
492 void dump(const Cfg *Func) const override; | 649 void dump(const Cfg *Func) const override; |
493 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } | 650 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } |
494 | 651 |
495 private: | 652 private: |
496 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem); | 653 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 654 CondARM32::Cond Predicate); |
497 ~InstARM32Ldr() override {} | 655 ~InstARM32Ldr() override {} |
498 }; | 656 }; |
499 | 657 |
500 // Multiply Accumulate: d := x * y + a | 658 // Multiply Accumulate: d := x * y + a |
501 class InstARM32Mla : public InstARM32 { | 659 class InstARM32Mla : public InstARM32Pred { |
502 InstARM32Mla() = delete; | 660 InstARM32Mla() = delete; |
503 InstARM32Mla(const InstARM32Mla &) = delete; | 661 InstARM32Mla(const InstARM32Mla &) = delete; |
504 InstARM32Mla &operator=(const InstARM32Mla &) = delete; | 662 InstARM32Mla &operator=(const InstARM32Mla &) = delete; |
505 | 663 |
506 public: | 664 public: |
507 // Everything must be a register. | 665 // Everything must be a register. |
508 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, | 666 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, |
509 Variable *Src1, Variable *Acc) { | 667 Variable *Src1, Variable *Acc, |
| 668 CondARM32::Cond Predicate) { |
510 return new (Func->allocate<InstARM32Mla>()) | 669 return new (Func->allocate<InstARM32Mla>()) |
511 InstARM32Mla(Func, Dest, Src0, Src1, Acc); | 670 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); |
512 } | 671 } |
513 void emit(const Cfg *Func) const override; | 672 void emit(const Cfg *Func) const override; |
514 void emitIAS(const Cfg *Func) const override; | 673 void emitIAS(const Cfg *Func) const override; |
515 void dump(const Cfg *Func) const override; | 674 void dump(const Cfg *Func) const override; |
516 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } | 675 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } |
517 | 676 |
518 private: | 677 private: |
519 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, | 678 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, |
520 Variable *Acc); | 679 Variable *Acc, CondARM32::Cond Predicate); |
521 ~InstARM32Mla() override {} | 680 ~InstARM32Mla() override {} |
522 }; | 681 }; |
523 | 682 |
524 // Ret pseudo-instruction. This is actually a "bx" instruction with | 683 // Ret pseudo-instruction. This is actually a "bx" instruction with |
525 // an "lr" register operand, but epilogue lowering will search for a Ret | 684 // an "lr" register operand, but epilogue lowering will search for a Ret |
526 // instead of a generic "bx". This instruction also takes a Source | 685 // instead of a generic "bx". This instruction also takes a Source |
527 // operand (for non-void returning functions) for liveness analysis, though | 686 // operand (for non-void returning functions) for liveness analysis, though |
528 // a FakeUse before the ret would do just as well. | 687 // a FakeUse before the ret would do just as well. |
| 688 // |
| 689 // NOTE: Even though "bx" can be predicated, for now leave out the predication |
| 690 // since it's not yet known to be useful for Ret. That may complicate finding |
| 691 // the terminator instruction if it's not guaranteed to be executed. |
529 class InstARM32Ret : public InstARM32 { | 692 class InstARM32Ret : public InstARM32 { |
530 InstARM32Ret() = delete; | 693 InstARM32Ret() = delete; |
531 InstARM32Ret(const InstARM32Ret &) = delete; | 694 InstARM32Ret(const InstARM32Ret &) = delete; |
532 InstARM32Ret &operator=(const InstARM32Ret &) = delete; | 695 InstARM32Ret &operator=(const InstARM32Ret &) = delete; |
533 | 696 |
534 public: | 697 public: |
535 static InstARM32Ret *create(Cfg *Func, Variable *LR, | 698 static InstARM32Ret *create(Cfg *Func, Variable *LR, |
536 Variable *Source = nullptr) { | 699 Variable *Source = nullptr) { |
537 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); | 700 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); |
538 } | 701 } |
539 void emit(const Cfg *Func) const override; | 702 void emit(const Cfg *Func) const override; |
540 void emitIAS(const Cfg *Func) const override; | 703 void emitIAS(const Cfg *Func) const override; |
541 void dump(const Cfg *Func) const override; | 704 void dump(const Cfg *Func) const override; |
542 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 705 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
543 | 706 |
544 private: | 707 private: |
545 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); | 708 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); |
546 ~InstARM32Ret() override {} | 709 ~InstARM32Ret() override {} |
547 }; | 710 }; |
548 | 711 |
549 // Unsigned Multiply Long: d.lo, d.hi := x * y | 712 // Unsigned Multiply Long: d.lo, d.hi := x * y |
550 class InstARM32Umull : public InstARM32 { | 713 class InstARM32Umull : public InstARM32Pred { |
551 InstARM32Umull() = delete; | 714 InstARM32Umull() = delete; |
552 InstARM32Umull(const InstARM32Umull &) = delete; | 715 InstARM32Umull(const InstARM32Umull &) = delete; |
553 InstARM32Umull &operator=(const InstARM32Umull &) = delete; | 716 InstARM32Umull &operator=(const InstARM32Umull &) = delete; |
554 | 717 |
555 public: | 718 public: |
556 // Everything must be a register. | 719 // Everything must be a register. |
557 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, | 720 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, |
558 Variable *Src0, Variable *Src1) { | 721 Variable *Src0, Variable *Src1, |
| 722 CondARM32::Cond Predicate) { |
559 return new (Func->allocate<InstARM32Umull>()) | 723 return new (Func->allocate<InstARM32Umull>()) |
560 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1); | 724 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); |
561 } | 725 } |
562 void emit(const Cfg *Func) const override; | 726 void emit(const Cfg *Func) const override; |
563 void emitIAS(const Cfg *Func) const override; | 727 void emitIAS(const Cfg *Func) const override; |
564 void dump(const Cfg *Func) const override; | 728 void dump(const Cfg *Func) const override; |
565 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } | 729 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } |
566 | 730 |
567 private: | 731 private: |
568 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, | 732 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, |
569 Variable *Src1); | 733 Variable *Src1, CondARM32::Cond Predicate); |
570 ~InstARM32Umull() override {} | 734 ~InstARM32Umull() override {} |
571 Variable *DestHi; | 735 Variable *DestHi; |
572 }; | 736 }; |
573 | 737 |
574 // Declare partial template specializations of emit() methods that | 738 // Declare partial template specializations of emit() methods that |
575 // already have default implementations. Without this, there is the | 739 // already have default implementations. Without this, there is the |
576 // possibility of ODR violations and link errors. | 740 // possibility of ODR violations and link errors. |
577 | 741 |
578 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 742 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
579 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 743 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
580 | 744 |
581 } // end of namespace Ice | 745 } // end of namespace Ice |
582 | 746 |
583 #endif // SUBZERO_SRC_ICEINSTARM32_H | 747 #endif // SUBZERO_SRC_ICEINSTARM32_H |
OLD | NEW |