WebAssemblySetP2AlignOperands.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file sets the p2align operands on load and store instructions.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
  14. #include "WebAssembly.h"
  15. #include "WebAssemblyInstrInfo.h"
  16. #include "WebAssemblyMachineFunctionInfo.h"
  17. #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
  18. #include "llvm/CodeGen/MachineMemOperand.h"
  19. #include "llvm/CodeGen/Passes.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. using namespace llvm;
  23. #define DEBUG_TYPE "wasm-set-p2align-operands"
  24. namespace {
  25. class WebAssemblySetP2AlignOperands final : public MachineFunctionPass {
  26. public:
  27. static char ID; // Pass identification, replacement for typeid
  28. WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {}
  29. StringRef getPassName() const override {
  30. return "WebAssembly Set p2align Operands";
  31. }
  32. void getAnalysisUsage(AnalysisUsage &AU) const override {
  33. AU.setPreservesCFG();
  34. AU.addPreserved<MachineBlockFrequencyInfo>();
  35. AU.addPreservedID(MachineDominatorsID);
  36. MachineFunctionPass::getAnalysisUsage(AU);
  37. }
  38. bool runOnMachineFunction(MachineFunction &MF) override;
  39. };
  40. } // end anonymous namespace
  41. char WebAssemblySetP2AlignOperands::ID = 0;
  42. INITIALIZE_PASS(WebAssemblySetP2AlignOperands, DEBUG_TYPE,
  43. "Set the p2align operands for WebAssembly loads and stores",
  44. false, false)
  45. FunctionPass *llvm::createWebAssemblySetP2AlignOperands() {
  46. return new WebAssemblySetP2AlignOperands();
  47. }
  48. static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
  49. assert(MI.getOperand(OperandNo).getImm() == 0 &&
  50. "ISel should set p2align operands to 0");
  51. assert(MI.hasOneMemOperand() &&
  52. "Load and store instructions have exactly one mem operand");
  53. assert((*MI.memoperands_begin())->getSize() ==
  54. (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
  55. "Default p2align value should be natural");
  56. assert(MI.getDesc().operands()[OperandNo].OperandType ==
  57. WebAssembly::OPERAND_P2ALIGN &&
  58. "Load and store instructions should have a p2align operand");
  59. uint64_t P2Align = Log2((*MI.memoperands_begin())->getAlign());
  60. // WebAssembly does not currently support supernatural alignment.
  61. P2Align = std::min(P2Align,
  62. uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
  63. MI.getOperand(OperandNo).setImm(P2Align);
  64. }
  65. bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) {
  66. LLVM_DEBUG({
  67. dbgs() << "********** Set p2align Operands **********\n"
  68. << "********** Function: " << MF.getName() << '\n';
  69. });
  70. bool Changed = false;
  71. for (auto &MBB : MF) {
  72. for (auto &MI : MBB) {
  73. int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx(
  74. MI.getOpcode(), WebAssembly::OpName::p2align);
  75. if (P2AlignOpNum != -1) {
  76. rewriteP2Align(MI, P2AlignOpNum);
  77. Changed = true;
  78. }
  79. }
  80. }
  81. return Changed;
  82. }