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