CSEMIRBuilder.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. /// This file implements a version of MachineIRBuilder which CSEs insts within
  15. /// a MachineBasicBlock.
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
  18. #define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
  19. #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
  20. namespace llvm {
  21. class GISelInstProfileBuilder;
  22. /// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
  23. /// Eg usage.
  24. ///
  25. ///
  26. /// GISelCSEInfo *Info =
  27. /// &getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEInfo(); CSEMIRBuilder
  28. /// CB(Builder.getState()); CB.setCSEInfo(Info); auto A = CB.buildConstant(s32,
  29. /// 42); auto B = CB.buildConstant(s32, 42); assert(A == B); unsigned CReg =
  30. /// MRI.createGenericVirtualRegister(s32); auto C = CB.buildConstant(CReg, 42);
  31. /// assert(C->getOpcode() == TargetOpcode::COPY);
  32. /// Explicitly passing in a register would materialize a copy if possible.
  33. /// CSEMIRBuilder also does trivial constant folding for binary ops.
  34. class CSEMIRBuilder : public MachineIRBuilder {
  35. /// Returns true if A dominates B (within the same basic block).
  36. /// Both iterators must be in the same basic block.
  37. //
  38. // TODO: Another approach for checking dominance is having two iterators and
  39. // making them go towards each other until they meet or reach begin/end. Which
  40. // approach is better? Should this even change dynamically? For G_CONSTANTS
  41. // most of which will be at the top of the BB, the top down approach would be
  42. // a better choice. Does IRTranslator placing constants at the beginning still
  43. // make sense? Should this change based on Opcode?
  44. bool dominates(MachineBasicBlock::const_iterator A,
  45. MachineBasicBlock::const_iterator B) const;
  46. /// For given ID, find a machineinstr in the CSE Map. If found, check if it
  47. /// dominates the current insertion point and if not, move it just before the
  48. /// current insertion point and return it. If not found, return Null
  49. /// MachineInstrBuilder.
  50. MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID,
  51. void *&NodeInsertPos);
  52. /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is
  53. /// safe to CSE.
  54. bool canPerformCSEForOpc(unsigned Opc) const;
  55. void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const;
  56. void profileDstOps(ArrayRef<DstOp> Ops, GISelInstProfileBuilder &B) const {
  57. for (const DstOp &Op : Ops)
  58. profileDstOp(Op, B);
  59. }
  60. void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const;
  61. void profileSrcOps(ArrayRef<SrcOp> Ops, GISelInstProfileBuilder &B) const {
  62. for (const SrcOp &Op : Ops)
  63. profileSrcOp(Op, B);
  64. }
  65. void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const;
  66. void profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps,
  67. ArrayRef<SrcOp> SrcOps, std::optional<unsigned> Flags,
  68. GISelInstProfileBuilder &B) const;
  69. // Takes a MachineInstrBuilder and inserts it into the CSEMap using the
  70. // NodeInsertPos.
  71. MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos);
  72. // If we have can CSE an instruction, but still need to materialize to a VReg,
  73. // we emit a copy from the CSE'd inst to the VReg.
  74. MachineInstrBuilder generateCopiesIfRequired(ArrayRef<DstOp> DstOps,
  75. MachineInstrBuilder &MIB);
  76. // If we have can CSE an instruction, but still need to materialize to a VReg,
  77. // check if we can generate copies. It's not possible to return a single MIB,
  78. // while emitting copies to multiple vregs.
  79. bool checkCopyToDefsPossible(ArrayRef<DstOp> DstOps);
  80. public:
  81. // Pull in base class constructors.
  82. using MachineIRBuilder::MachineIRBuilder;
  83. // Unhide buildInstr
  84. MachineInstrBuilder
  85. buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps,
  86. std::optional<unsigned> Flag = std::nullopt) override;
  87. // Bring in the other overload from the base class.
  88. using MachineIRBuilder::buildConstant;
  89. MachineInstrBuilder buildConstant(const DstOp &Res,
  90. const ConstantInt &Val) override;
  91. // Bring in the other overload from the base class.
  92. using MachineIRBuilder::buildFConstant;
  93. MachineInstrBuilder buildFConstant(const DstOp &Res,
  94. const ConstantFP &Val) override;
  95. };
  96. } // namespace llvm
  97. #endif
  98. #ifdef __GNUC__
  99. #pragma GCC diagnostic pop
  100. #endif