1303231Sdim//=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim/// 9303231Sdim/// \file 10341825Sdim/// This file sets the p2align operands on load and store instructions. 11303231Sdim/// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14321369Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 15303231Sdim#include "WebAssembly.h" 16353358Sdim#include "WebAssemblyInstrInfo.h" 17303231Sdim#include "WebAssemblyMachineFunctionInfo.h" 18303231Sdim#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 19303231Sdim#include "llvm/CodeGen/MachineMemOperand.h" 20303231Sdim#include "llvm/CodeGen/Passes.h" 21303231Sdim#include "llvm/Support/Debug.h" 22303231Sdim#include "llvm/Support/raw_ostream.h" 23303231Sdimusing namespace llvm; 24303231Sdim 25303231Sdim#define DEBUG_TYPE "wasm-set-p2align-operands" 26303231Sdim 27303231Sdimnamespace { 28303231Sdimclass WebAssemblySetP2AlignOperands final : public MachineFunctionPass { 29303231Sdimpublic: 30303231Sdim static char ID; // Pass identification, replacement for typeid 31303231Sdim WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {} 32303231Sdim 33314564Sdim StringRef getPassName() const override { 34303231Sdim return "WebAssembly Set p2align Operands"; 35303231Sdim } 36303231Sdim 37303231Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 38303231Sdim AU.setPreservesCFG(); 39303231Sdim AU.addPreserved<MachineBlockFrequencyInfo>(); 40303231Sdim AU.addPreservedID(MachineDominatorsID); 41303231Sdim MachineFunctionPass::getAnalysisUsage(AU); 42303231Sdim } 43303231Sdim 44303231Sdim bool runOnMachineFunction(MachineFunction &MF) override; 45303231Sdim}; 46303231Sdim} // end anonymous namespace 47303231Sdim 48303231Sdimchar WebAssemblySetP2AlignOperands::ID = 0; 49341825SdimINITIALIZE_PASS(WebAssemblySetP2AlignOperands, DEBUG_TYPE, 50341825Sdim "Set the p2align operands for WebAssembly loads and stores", 51341825Sdim false, false) 52341825Sdim 53303231SdimFunctionPass *llvm::createWebAssemblySetP2AlignOperands() { 54303231Sdim return new WebAssemblySetP2AlignOperands(); 55303231Sdim} 56303231Sdim 57353358Sdimstatic void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) { 58314564Sdim assert(MI.getOperand(OperandNo).getImm() == 0 && 59314564Sdim "ISel should set p2align operands to 0"); 60314564Sdim assert(MI.hasOneMemOperand() && 61314564Sdim "Load and store instructions have exactly one mem operand"); 62314564Sdim assert((*MI.memoperands_begin())->getSize() == 63344779Sdim (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) && 64314564Sdim "Default p2align value should be natural"); 65314564Sdim assert(MI.getDesc().OpInfo[OperandNo].OperandType == 66314564Sdim WebAssembly::OPERAND_P2ALIGN && 67314564Sdim "Load and store instructions should have a p2align operand"); 68314564Sdim uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); 69314564Sdim 70314564Sdim // WebAssembly does not currently support supernatural alignment. 71344779Sdim P2Align = std::min(P2Align, 72344779Sdim uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); 73314564Sdim 74314564Sdim MI.getOperand(OperandNo).setImm(P2Align); 75314564Sdim} 76314564Sdim 77303231Sdimbool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { 78341825Sdim LLVM_DEBUG({ 79303231Sdim dbgs() << "********** Set p2align Operands **********\n" 80303231Sdim << "********** Function: " << MF.getName() << '\n'; 81303231Sdim }); 82303231Sdim 83303231Sdim bool Changed = false; 84303231Sdim 85303231Sdim for (auto &MBB : MF) { 86303231Sdim for (auto &MI : MBB) { 87353358Sdim int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx( 88353358Sdim MI.getOpcode(), WebAssembly::OpName::p2align); 89353358Sdim if (P2AlignOpNum != -1) { 90353358Sdim rewriteP2Align(MI, P2AlignOpNum); 91353358Sdim Changed = true; 92303231Sdim } 93303231Sdim } 94303231Sdim } 95303231Sdim 96303231Sdim return Changed; 97303231Sdim} 98