xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file sets the p2align operands on load and store instructions.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
150b57cec5SDimitry Andric #include "WebAssembly.h"
160b57cec5SDimitry Andric #include "WebAssemblyInstrInfo.h"
170b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-set-p2align-operands"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric class WebAssemblySetP2AlignOperands final : public MachineFunctionPass {
290b57cec5SDimitry Andric public:
300b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
WebAssemblySetP2AlignOperands()310b57cec5SDimitry Andric   WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {}
320b57cec5SDimitry Andric 
getPassName() const330b57cec5SDimitry Andric   StringRef getPassName() const override {
340b57cec5SDimitry Andric     return "WebAssembly Set p2align Operands";
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const370b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
380b57cec5SDimitry Andric     AU.setPreservesCFG();
39*0fca6ea1SDimitry Andric     AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
400b57cec5SDimitry Andric     AU.addPreservedID(MachineDominatorsID);
410b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
450b57cec5SDimitry Andric };
460b57cec5SDimitry Andric } // end anonymous namespace
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric char WebAssemblySetP2AlignOperands::ID = 0;
490b57cec5SDimitry Andric INITIALIZE_PASS(WebAssemblySetP2AlignOperands, DEBUG_TYPE,
500b57cec5SDimitry Andric                 "Set the p2align operands for WebAssembly loads and stores",
510b57cec5SDimitry Andric                 false, false)
520b57cec5SDimitry Andric 
createWebAssemblySetP2AlignOperands()530b57cec5SDimitry Andric FunctionPass *llvm::createWebAssemblySetP2AlignOperands() {
540b57cec5SDimitry Andric   return new WebAssemblySetP2AlignOperands();
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
rewriteP2Align(MachineInstr & MI,unsigned OperandNo)570b57cec5SDimitry Andric static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
580b57cec5SDimitry Andric   assert(MI.getOperand(OperandNo).getImm() == 0 &&
590b57cec5SDimitry Andric          "ISel should set p2align operands to 0");
600b57cec5SDimitry Andric   assert(MI.hasOneMemOperand() &&
610b57cec5SDimitry Andric          "Load and store instructions have exactly one mem operand");
620b57cec5SDimitry Andric   assert((*MI.memoperands_begin())->getSize() ==
630b57cec5SDimitry Andric              (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
640b57cec5SDimitry Andric          "Default p2align value should be natural");
65bdd1243dSDimitry Andric   assert(MI.getDesc().operands()[OperandNo].OperandType ==
660b57cec5SDimitry Andric              WebAssembly::OPERAND_P2ALIGN &&
670b57cec5SDimitry Andric          "Load and store instructions should have a p2align operand");
685ffd83dbSDimitry Andric   uint64_t P2Align = Log2((*MI.memoperands_begin())->getAlign());
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   // WebAssembly does not currently support supernatural alignment.
710b57cec5SDimitry Andric   P2Align = std::min(P2Align,
720b57cec5SDimitry Andric                      uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   MI.getOperand(OperandNo).setImm(P2Align);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)770b57cec5SDimitry Andric bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) {
780b57cec5SDimitry Andric   LLVM_DEBUG({
790b57cec5SDimitry Andric     dbgs() << "********** Set p2align Operands **********\n"
800b57cec5SDimitry Andric            << "********** Function: " << MF.getName() << '\n';
810b57cec5SDimitry Andric   });
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   bool Changed = false;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   for (auto &MBB : MF) {
860b57cec5SDimitry Andric     for (auto &MI : MBB) {
870b57cec5SDimitry Andric       int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx(
880b57cec5SDimitry Andric           MI.getOpcode(), WebAssembly::OpName::p2align);
890b57cec5SDimitry Andric       if (P2AlignOpNum != -1) {
900b57cec5SDimitry Andric         rewriteP2Align(MI, P2AlignOpNum);
910b57cec5SDimitry Andric         Changed = true;
920b57cec5SDimitry Andric       }
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   return Changed;
970b57cec5SDimitry Andric }
98