| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| 470 /// Generalizes scalarizeArithmetic to support other instruction types. | 474 /// Generalizes scalarizeArithmetic to support other instruction types. |
| 471 /// | 475 /// |
| 472 /// MakeInstruction is a function-like object with signature | 476 /// insertScalarInstruction is a function-like object with signature |
| 473 /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. | 477 /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. |
| 474 template <typename F> | 478 template <typename... Operands, |
| 475 void scalarizeInstruction(Variable *Dest, Operand *Src0, Operand *Src1, | 479 typename F = std::function<Inst *(Variable *, Operands *...)>> |
| 476 F &&MakeInstruction) { | 480 void scalarizeInstruction(Variable *Dest, F insertScalarInstruction, |
| 481 Operands *... Srcs) { |
| 482 assert(GeneratingTargetHelpers && |
| 483 "scalarizeInstruction called during incorrect phase"); |
| 477 const Type DestTy = Dest->getType(); | 484 const Type DestTy = Dest->getType(); |
| 478 assert(isVectorType(DestTy)); | 485 assert(isVectorType(DestTy)); |
| 479 const Type DestElementTy = typeElementType(DestTy); | 486 const Type DestElementTy = typeElementType(DestTy); |
| 480 const SizeT NumElements = typeNumElements(DestTy); | 487 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 | 488 |
| 487 Variable *T = Func->makeVariable(DestTy); | 489 Variable *T = Func->makeVariable(DestTy); |
| 488 Context.insert<InstFakeDef>(T); | 490 Context.insert<InstFakeDef>(T); |
| 491 |
| 489 for (SizeT I = 0; I < NumElements; ++I) { | 492 for (SizeT I = 0; I < NumElements; ++I) { |
| 490 Constant *Index = Ctx->getConstantInt32(I); | 493 auto *Index = Ctx->getConstantInt32(I); |
| 491 | 494 |
| 492 // Extract the next two inputs. | 495 auto makeExtractThunk = [this, Index, NumElements](Operand *Src) { |
| 493 Variable *Op0 = Func->makeVariable(Src0ElementTy); | 496 return [this, Index, NumElements, Src]() { |
| 494 Context.insert<InstExtractElement>(Op0, Src0, Index); | 497 assert(typeNumElements(Src->getType()) == NumElements); |
| 495 Variable *Op1 = Func->makeVariable(Src1ElementTy); | 498 |
| 496 Context.insert<InstExtractElement>(Op1, Src1, Index); | 499 const auto ElementTy = typeElementType(Src->getType()); |
| 500 auto *Op = Func->makeVariable(ElementTy); |
| 501 Context.insert<InstExtractElement>(Op, Src, Index); |
| 502 return Op; |
| 503 }; |
| 504 }; |
| 497 | 505 |
| 498 // Perform the operation as a scalar operation. | 506 // Perform the operation as a scalar operation. |
| 499 Variable *Res = Func->makeVariable(DestElementTy); | 507 auto *Res = Func->makeVariable(DestElementTy); |
| 500 auto Arith = MakeInstruction(Res, Op0, Op1); | 508 auto *Arith = applyToThunkedArgs(insertScalarInstruction, Res, |
| 501 // We might have created an operation that needed a helper call. | 509 makeExtractThunk(Srcs)...); |
| 502 genTargetHelperCallFor(Arith); | 510 genTargetHelperCallFor(Arith); |
| 503 | 511 |
| 504 // Insert the result into position. | |
| 505 Variable *DestT = Func->makeVariable(DestTy); | 512 Variable *DestT = Func->makeVariable(DestTy); |
| 506 Context.insert<InstInsertElement>(DestT, T, Res, Index); | 513 Context.insert<InstInsertElement>(DestT, T, Res, Index); |
| 507 T = DestT; | 514 T = DestT; |
| 508 } | 515 } |
| 509 Context.insert<InstAssign>(Dest, T); | 516 Context.insert<InstAssign>(Dest, T); |
| 510 } | 517 } |
| 511 | 518 |
| 512 template <typename F> | 519 // applyToThunkedArgs is used by scalarizeInstruction. Ideally, we would just |
| 513 void scalarizeUnaryInstruction(Variable *Dest, Operand *Src0, | 520 // call insertScalarInstruction(Res, Srcs...), but C++ does not specify |
| 514 F &&MakeInstruction) { | 521 // evaluation order which means this leads to an unpredictable final |
| 515 const Type DestTy = Dest->getType(); | 522 // output. Instead, we wrap each of the Srcs in a thunk and these |
| 516 assert(isVectorType(DestTy)); | 523 // applyToThunkedArgs functions apply the thunks in a well defined order so we |
| 517 const Type DestElementTy = typeElementType(DestTy); | 524 // still get well-defined output. |
| 518 const SizeT NumElements = typeNumElements(DestTy); | 525 Inst *applyToThunkedArgs( |
| 519 const Type Src0ElementTy = typeElementType(Src0->getType()); | 526 std::function<Inst *(Variable *, Variable *)> insertScalarInstruction, |
| 527 Variable *Res, std::function<Variable *()> thunk0) { |
| 528 auto *Src0 = thunk0(); |
| 529 return insertScalarInstruction(Res, Src0); |
| 530 } |
| 520 | 531 |
| 521 assert(NumElements == typeNumElements(Src0->getType())); | 532 Inst * |
| 533 applyToThunkedArgs(std::function<Inst *(Variable *, Variable *, Variable *)> |
| 534 insertScalarInstruction, |
| 535 Variable *Res, std::function<Variable *()> thunk0, |
| 536 std::function<Variable *()> thunk1) { |
| 537 auto *Src0 = thunk0(); |
| 538 auto *Src1 = thunk1(); |
| 539 return insertScalarInstruction(Res, Src0, Src1); |
| 540 } |
| 522 | 541 |
| 523 Variable *T = Func->makeVariable(DestTy); | 542 Inst *applyToThunkedArgs( |
| 524 Context.insert<InstFakeDef>(T); | 543 std::function<Inst *(Variable *, Variable *, Variable *, Variable *)> |
| 525 for (SizeT I = 0; I < NumElements; ++I) { | 544 insertScalarInstruction, |
| 526 Constant *Index = Ctx->getConstantInt32(I); | 545 Variable *Res, std::function<Variable *()> thunk0, |
| 527 | 546 std::function<Variable *()> thunk1, std::function<Variable *()> thunk2) { |
| 528 // Extract the next two inputs. | 547 auto *Src0 = thunk0(); |
| 529 Variable *Op0 = Func->makeVariable(Src0ElementTy); | 548 auto *Src1 = thunk1(); |
| 530 Context.insert<InstExtractElement>(Op0, Src0, Index); | 549 auto *Src2 = thunk2(); |
| 531 | 550 return insertScalarInstruction(Res, Src0, Src1, Src2); |
| 532 // Perform the operation as a scalar operation. | |
| 533 Variable *Res = Func->makeVariable(DestElementTy); | |
| 534 auto Arith = MakeInstruction(Res, Op0); | |
| 535 // We might have created an operation that needed a helper call. | |
| 536 genTargetHelperCallFor(Arith); | |
| 537 | |
| 538 // Insert the result into position. | |
| 539 Variable *DestT = Func->makeVariable(DestTy); | |
| 540 Context.insert<InstInsertElement>(DestT, T, Res, Index); | |
| 541 T = DestT; | |
| 542 } | |
| 543 Context.insert<InstAssign>(Dest, T); | |
| 544 } | 551 } |
| 545 | 552 |
| 546 /// SandboxType enumerates all possible sandboxing strategies that | 553 /// SandboxType enumerates all possible sandboxing strategies that |
| 547 enum SandboxType { | 554 enum SandboxType { |
| 548 ST_None, | 555 ST_None, |
| 549 ST_NaCl, | 556 ST_NaCl, |
| 550 ST_Nonsfi, | 557 ST_Nonsfi, |
| 551 }; | 558 }; |
| 552 | 559 |
| 553 static SandboxType determineSandboxTypeFromFlags(const ClFlags &Flags); | 560 static SandboxType determineSandboxTypeFromFlags(const ClFlags &Flags); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 virtual void lower() {} | 654 virtual void lower() {} |
| 648 | 655 |
| 649 protected: | 656 protected: |
| 650 explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} | 657 explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} |
| 651 GlobalContext *Ctx; | 658 GlobalContext *Ctx; |
| 652 }; | 659 }; |
| 653 | 660 |
| 654 } // end of namespace Ice | 661 } // end of namespace Ice |
| 655 | 662 |
| 656 #endif // SUBZERO_SRC_ICETARGETLOWERING_H | 663 #endif // SUBZERO_SRC_ICETARGETLOWERING_H |
| OLD | NEW |