xref: /src/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
101095a5dSDimitry Andric //=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric ///
901095a5dSDimitry Andric /// \file
10eb11fae6SDimitry Andric /// This file sets the p2align operands on load and store instructions.
1101095a5dSDimitry Andric ///
1201095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1301095a5dSDimitry Andric 
1401095a5dSDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
157ab83427SDimitry Andric #include "WebAssembly.h"
16e6d15924SDimitry Andric #include "WebAssemblyInstrInfo.h"
1701095a5dSDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
1801095a5dSDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
1901095a5dSDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
2001095a5dSDimitry Andric #include "llvm/CodeGen/Passes.h"
2101095a5dSDimitry Andric #include "llvm/Support/Debug.h"
2201095a5dSDimitry Andric #include "llvm/Support/raw_ostream.h"
2301095a5dSDimitry Andric using namespace llvm;
2401095a5dSDimitry Andric 
2501095a5dSDimitry Andric #define DEBUG_TYPE "wasm-set-p2align-operands"
2601095a5dSDimitry Andric 
2701095a5dSDimitry Andric namespace {
2801095a5dSDimitry Andric class WebAssemblySetP2AlignOperands final : public MachineFunctionPass {
2901095a5dSDimitry Andric public:
3001095a5dSDimitry Andric   static char ID; // Pass identification, replacement for typeid
WebAssemblySetP2AlignOperands()3101095a5dSDimitry Andric   WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {}
3201095a5dSDimitry Andric 
getPassName() const33b915e9e0SDimitry Andric   StringRef getPassName() const override {
3401095a5dSDimitry Andric     return "WebAssembly Set p2align Operands";
3501095a5dSDimitry Andric   }
3601095a5dSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const3701095a5dSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3801095a5dSDimitry Andric     AU.setPreservesCFG();
39ac9a064cSDimitry Andric     AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
4001095a5dSDimitry Andric     AU.addPreservedID(MachineDominatorsID);
4101095a5dSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
4201095a5dSDimitry Andric   }
4301095a5dSDimitry Andric 
4401095a5dSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
4501095a5dSDimitry Andric };
4601095a5dSDimitry Andric } // end anonymous namespace
4701095a5dSDimitry Andric 
4801095a5dSDimitry Andric char WebAssemblySetP2AlignOperands::ID = 0;
49eb11fae6SDimitry Andric INITIALIZE_PASS(WebAssemblySetP2AlignOperands, DEBUG_TYPE,
50eb11fae6SDimitry Andric                 "Set the p2align operands for WebAssembly loads and stores",
51eb11fae6SDimitry Andric                 false, false)
52eb11fae6SDimitry Andric 
createWebAssemblySetP2AlignOperands()5301095a5dSDimitry Andric FunctionPass *llvm::createWebAssemblySetP2AlignOperands() {
5401095a5dSDimitry Andric   return new WebAssemblySetP2AlignOperands();
5501095a5dSDimitry Andric }
5601095a5dSDimitry Andric 
rewriteP2Align(MachineInstr & MI,unsigned OperandNo)57e6d15924SDimitry Andric static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
58b915e9e0SDimitry Andric   assert(MI.getOperand(OperandNo).getImm() == 0 &&
59b915e9e0SDimitry Andric          "ISel should set p2align operands to 0");
60b915e9e0SDimitry Andric   assert(MI.hasOneMemOperand() &&
61b915e9e0SDimitry Andric          "Load and store instructions have exactly one mem operand");
62b915e9e0SDimitry Andric   assert((*MI.memoperands_begin())->getSize() ==
63d8e91e46SDimitry Andric              (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
64b915e9e0SDimitry Andric          "Default p2align value should be natural");
65e3b55780SDimitry Andric   assert(MI.getDesc().operands()[OperandNo].OperandType ==
66b915e9e0SDimitry Andric              WebAssembly::OPERAND_P2ALIGN &&
67b915e9e0SDimitry Andric          "Load and store instructions should have a p2align operand");
68cfca06d7SDimitry Andric   uint64_t P2Align = Log2((*MI.memoperands_begin())->getAlign());
69b915e9e0SDimitry Andric 
70b915e9e0SDimitry Andric   // WebAssembly does not currently support supernatural alignment.
71d8e91e46SDimitry Andric   P2Align = std::min(P2Align,
72d8e91e46SDimitry Andric                      uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
73b915e9e0SDimitry Andric 
74b915e9e0SDimitry Andric   MI.getOperand(OperandNo).setImm(P2Align);
75b915e9e0SDimitry Andric }
76b915e9e0SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)7701095a5dSDimitry Andric bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) {
78eb11fae6SDimitry Andric   LLVM_DEBUG({
7901095a5dSDimitry Andric     dbgs() << "********** Set p2align Operands **********\n"
8001095a5dSDimitry Andric            << "********** Function: " << MF.getName() << '\n';
8101095a5dSDimitry Andric   });
8201095a5dSDimitry Andric 
8301095a5dSDimitry Andric   bool Changed = false;
8401095a5dSDimitry Andric 
8501095a5dSDimitry Andric   for (auto &MBB : MF) {
8601095a5dSDimitry Andric     for (auto &MI : MBB) {
87e6d15924SDimitry Andric       int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx(
88e6d15924SDimitry Andric           MI.getOpcode(), WebAssembly::OpName::p2align);
89e6d15924SDimitry Andric       if (P2AlignOpNum != -1) {
90e6d15924SDimitry Andric         rewriteP2Align(MI, P2AlignOpNum);
91e6d15924SDimitry Andric         Changed = true;
9201095a5dSDimitry Andric       }
9301095a5dSDimitry Andric     }
9401095a5dSDimitry Andric   }
9501095a5dSDimitry Andric 
9601095a5dSDimitry Andric   return Changed;
9701095a5dSDimitry Andric }
98