Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: src/IceInstARM32.h

Issue 1151663004: Subzero ARM: do lowerIcmp, lowerBr, and a bit of lowerCall. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: fix Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceConditionCodesARM32.h ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « src/IceConditionCodesARM32.h ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698