OLD | NEW |
1 //===- subzero/src/IceTargetLowering.h - Lowering interface -----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLowering.h - Lowering interface -----*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 virtual void addProlog(CfgNode *Node) = 0; | 318 virtual void addProlog(CfgNode *Node) = 0; |
319 virtual void addEpilog(CfgNode *Node) = 0; | 319 virtual void addEpilog(CfgNode *Node) = 0; |
320 | 320 |
321 virtual ~TargetLowering() = default; | 321 virtual ~TargetLowering() = default; |
322 | 322 |
323 private: | 323 private: |
324 // This control variable is used by AutoBundle (RAII-style bundle | 324 // This control variable is used by AutoBundle (RAII-style bundle |
325 // locking/unlocking) to prevent nested bundles. | 325 // locking/unlocking) to prevent nested bundles. |
326 bool AutoBundling = false; | 326 bool AutoBundling = false; |
327 | 327 |
| 328 /// This indicates whether we are in the genTargetHelperCalls phase, and |
| 329 /// therefore can do things like scalarization. |
| 330 bool GeneratingTargetHelpers = false; |
| 331 |
328 // _bundle_lock(), and _bundle_unlock(), were made private to force subtargets | 332 // _bundle_lock(), and _bundle_unlock(), were made private to force subtargets |
329 // to use the AutoBundle helper. | 333 // to use the AutoBundle helper. |
330 void | 334 void |
331 _bundle_lock(InstBundleLock::Option BundleOption = InstBundleLock::Opt_None) { | 335 _bundle_lock(InstBundleLock::Option BundleOption = InstBundleLock::Opt_None) { |
332 Context.insert<InstBundleLock>(BundleOption); | 336 Context.insert<InstBundleLock>(BundleOption); |
333 } | 337 } |
334 void _bundle_unlock() { Context.insert<InstBundleUnlock>(); } | 338 void _bundle_unlock() { Context.insert<InstBundleUnlock>(); } |
335 | 339 |
336 protected: | 340 protected: |
337 /// AutoBundle provides RIAA-style bundling. Sub-targets are expected to use | 341 /// AutoBundle provides RIAA-style bundling. Sub-targets are expected to use |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 InstCall *makeHelperCall(const IceString &Name, Variable *Dest, | 464 InstCall *makeHelperCall(const IceString &Name, Variable *Dest, |
461 SizeT MaxSrcs); | 465 SizeT MaxSrcs); |
462 | 466 |
463 void _set_dest_redefined() { Context.getLastInserted()->setDestRedefined(); } | 467 void _set_dest_redefined() { Context.getLastInserted()->setDestRedefined(); } |
464 | 468 |
465 bool shouldOptimizeMemIntrins(); | 469 bool shouldOptimizeMemIntrins(); |
466 | 470 |
467 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, | 471 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, |
468 Operand *Src0, Operand *Src1); | 472 Operand *Src0, Operand *Src1); |
469 | 473 |
| 474 Variable *makeExtract(Operand *Src, Operand *Index); |
| 475 |
470 /// Generalizes scalarizeArithmetic to support other instruction types. | 476 /// Generalizes scalarizeArithmetic to support other instruction types. |
471 /// | 477 /// |
472 /// MakeInstruction is a function-like object with signature | 478 /// insertScalarInstruction is a function-like object with signature |
473 /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. | 479 /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. |
474 template <typename F> | 480 void scalarizeInstruction( |
475 void scalarizeInstruction(Variable *Dest, Operand *Src0, Operand *Src1, | 481 Variable *Dest, |
476 F &&MakeInstruction) { | 482 std::function<Inst *(Variable *, Variable *)> insertScalarInstruction, |
| 483 Operand *Src0) { |
| 484 assert(GeneratingTargetHelpers && |
| 485 "scalarizeInstruction called during incorrect phase"); |
477 const Type DestTy = Dest->getType(); | 486 const Type DestTy = Dest->getType(); |
478 assert(isVectorType(DestTy)); | 487 assert(isVectorType(DestTy)); |
479 const Type DestElementTy = typeElementType(DestTy); | 488 const Type DestElementTy = typeElementType(DestTy); |
480 const SizeT NumElements = typeNumElements(DestTy); | 489 const SizeT NumElements = typeNumElements(DestTy); |
481 const Type Src0ElementTy = typeElementType(Src0->getType()); | |
482 const Type Src1ElementTy = typeElementType(Src1->getType()); | |
483 | |
484 assert(NumElements == typeNumElements(Src0->getType())); | |
485 assert(NumElements == typeNumElements(Src1->getType())); | |
486 | 490 |
487 Variable *T = Func->makeVariable(DestTy); | 491 Variable *T = Func->makeVariable(DestTy); |
488 Context.insert<InstFakeDef>(T); | 492 Context.insert<InstFakeDef>(T); |
| 493 |
489 for (SizeT I = 0; I < NumElements; ++I) { | 494 for (SizeT I = 0; I < NumElements; ++I) { |
490 Constant *Index = Ctx->getConstantInt32(I); | 495 auto *Index = Ctx->getConstantInt32(I); |
491 | 496 |
492 // Extract the next two inputs. | 497 auto *Op0 = makeExtract(Src0, Index); |
493 Variable *Op0 = Func->makeVariable(Src0ElementTy); | |
494 Context.insert<InstExtractElement>(Op0, Src0, Index); | |
495 Variable *Op1 = Func->makeVariable(Src1ElementTy); | |
496 Context.insert<InstExtractElement>(Op1, Src1, Index); | |
497 | 498 |
498 // Perform the operation as a scalar operation. | 499 // Perform the operation as a scalar operation. |
499 Variable *Res = Func->makeVariable(DestElementTy); | 500 auto *Res = Func->makeVariable(DestElementTy); |
500 auto Arith = MakeInstruction(Res, Op0, Op1); | 501 auto *Arith = insertScalarInstruction(Res, Op0); |
501 // We might have created an operation that needed a helper call. | |
502 genTargetHelperCallFor(Arith); | 502 genTargetHelperCallFor(Arith); |
503 | 503 |
504 // Insert the result into position. | |
505 Variable *DestT = Func->makeVariable(DestTy); | 504 Variable *DestT = Func->makeVariable(DestTy); |
506 Context.insert<InstInsertElement>(DestT, T, Res, Index); | 505 Context.insert<InstInsertElement>(DestT, T, Res, Index); |
507 T = DestT; | 506 T = DestT; |
508 } | 507 } |
509 Context.insert<InstAssign>(Dest, T); | 508 Context.insert<InstAssign>(Dest, T); |
510 } | 509 } |
511 | 510 |
512 template <typename F> | 511 void |
513 void scalarizeUnaryInstruction(Variable *Dest, Operand *Src0, | 512 scalarizeInstruction(Variable *Dest, |
514 F &&MakeInstruction) { | 513 std::function<Inst *(Variable *, Variable *, Variable *)> |
| 514 insertScalarInstruction, |
| 515 Operand *Src0, Operand *Src1) { |
| 516 assert(GeneratingTargetHelpers && |
| 517 "scalarizeInstruction called during incorrect phase"); |
515 const Type DestTy = Dest->getType(); | 518 const Type DestTy = Dest->getType(); |
516 assert(isVectorType(DestTy)); | 519 assert(isVectorType(DestTy)); |
517 const Type DestElementTy = typeElementType(DestTy); | 520 const Type DestElementTy = typeElementType(DestTy); |
518 const SizeT NumElements = typeNumElements(DestTy); | 521 const SizeT NumElements = typeNumElements(DestTy); |
519 const Type Src0ElementTy = typeElementType(Src0->getType()); | |
520 | |
521 assert(NumElements == typeNumElements(Src0->getType())); | |
522 | 522 |
523 Variable *T = Func->makeVariable(DestTy); | 523 Variable *T = Func->makeVariable(DestTy); |
524 Context.insert<InstFakeDef>(T); | 524 Context.insert<InstFakeDef>(T); |
| 525 |
525 for (SizeT I = 0; I < NumElements; ++I) { | 526 for (SizeT I = 0; I < NumElements; ++I) { |
526 Constant *Index = Ctx->getConstantInt32(I); | 527 auto *Index = Ctx->getConstantInt32(I); |
527 | 528 |
528 // Extract the next two inputs. | 529 auto *Op0 = makeExtract(Src0, Index); |
529 Variable *Op0 = Func->makeVariable(Src0ElementTy); | 530 auto *Op1 = makeExtract(Src1, Index); |
530 Context.insert<InstExtractElement>(Op0, Src0, Index); | |
531 | 531 |
532 // Perform the operation as a scalar operation. | 532 // Perform the operation as a scalar operation. |
533 Variable *Res = Func->makeVariable(DestElementTy); | 533 auto *Res = Func->makeVariable(DestElementTy); |
534 auto Arith = MakeInstruction(Res, Op0); | 534 auto *Arith = insertScalarInstruction(Res, Op0, Op1); |
535 // We might have created an operation that needed a helper call. | |
536 genTargetHelperCallFor(Arith); | 535 genTargetHelperCallFor(Arith); |
537 | 536 |
538 // Insert the result into position. | |
539 Variable *DestT = Func->makeVariable(DestTy); | 537 Variable *DestT = Func->makeVariable(DestTy); |
540 Context.insert<InstInsertElement>(DestT, T, Res, Index); | 538 Context.insert<InstInsertElement>(DestT, T, Res, Index); |
541 T = DestT; | 539 T = DestT; |
| 540 } |
| 541 Context.insert<InstAssign>(Dest, T); |
| 542 } |
| 543 |
| 544 void scalarizeInstruction( |
| 545 Variable *Dest, std::function<Inst *(Variable *, Variable *, Variable *, |
| 546 Variable *)> insertScalarInstruction, |
| 547 Operand *Src0, Operand *Src1, Operand *Src2) { |
| 548 assert(GeneratingTargetHelpers && |
| 549 "scalarizeInstruction called during incorrect phase"); |
| 550 const Type DestTy = Dest->getType(); |
| 551 assert(isVectorType(DestTy)); |
| 552 const Type DestElementTy = typeElementType(DestTy); |
| 553 const SizeT NumElements = typeNumElements(DestTy); |
| 554 |
| 555 Variable *T = Func->makeVariable(DestTy); |
| 556 Context.insert<InstFakeDef>(T); |
| 557 |
| 558 for (SizeT I = 0; I < NumElements; ++I) { |
| 559 auto *Index = Ctx->getConstantInt32(I); |
| 560 |
| 561 auto *Op0 = makeExtract(Src0, Index); |
| 562 auto *Op1 = makeExtract(Src1, Index); |
| 563 auto *Op2 = makeExtract(Src2, Index); |
| 564 |
| 565 // Perform the operation as a scalar operation. |
| 566 auto *Res = Func->makeVariable(DestElementTy); |
| 567 auto *Arith = insertScalarInstruction(Res, Op0, Op1, Op2); |
| 568 genTargetHelperCallFor(Arith); |
| 569 |
| 570 Variable *DestT = Func->makeVariable(DestTy); |
| 571 Context.insert<InstInsertElement>(DestT, T, Res, Index); |
| 572 T = DestT; |
542 } | 573 } |
543 Context.insert<InstAssign>(Dest, T); | 574 Context.insert<InstAssign>(Dest, T); |
544 } | 575 } |
545 | 576 |
546 /// SandboxType enumerates all possible sandboxing strategies that | 577 /// SandboxType enumerates all possible sandboxing strategies that |
547 enum SandboxType { | 578 enum SandboxType { |
548 ST_None, | 579 ST_None, |
549 ST_NaCl, | 580 ST_NaCl, |
550 ST_Nonsfi, | 581 ST_Nonsfi, |
551 }; | 582 }; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 virtual void lower() {} | 678 virtual void lower() {} |
648 | 679 |
649 protected: | 680 protected: |
650 explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} | 681 explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} |
651 GlobalContext *Ctx; | 682 GlobalContext *Ctx; |
652 }; | 683 }; |
653 | 684 |
654 } // end of namespace Ice | 685 } // end of namespace Ice |
655 | 686 |
656 #endif // SUBZERO_SRC_ICETARGETLOWERING_H | 687 #endif // SUBZERO_SRC_ICETARGETLOWERING_H |
OLD | NEW |