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 14 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 15 #include "WebAssembly.h" 16 #include "WebAssemblyInstrInfo.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 24 #define DEBUG_TYPE "wasm-set-p2align-operands" 25 26 namespace { 27 class WebAssemblySetP2AlignOperands final : public MachineFunctionPass { 28 public: 29 static char ID; // Pass identification, replacement for typeid 30 WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {} 31 32 StringRef getPassName() const override { 33 return "WebAssembly Set p2align Operands"; 34 } 35 36 void getAnalysisUsage(AnalysisUsage &AU) const override { 37 AU.setPreservesCFG(); 38 AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>(); 39 AU.addPreservedID(MachineDominatorsID); 40 MachineFunctionPass::getAnalysisUsage(AU); 41 } 42 43 bool runOnMachineFunction(MachineFunction &MF) override; 44 }; 45 } // end anonymous namespace 46 47 char WebAssemblySetP2AlignOperands::ID = 0; 48 INITIALIZE_PASS(WebAssemblySetP2AlignOperands, DEBUG_TYPE, 49 "Set the p2align operands for WebAssembly loads and stores", 50 false, false) 51 52 FunctionPass *llvm::createWebAssemblySetP2AlignOperands() { 53 return new WebAssemblySetP2AlignOperands(); 54 } 55 56 static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) { 57 assert(MI.getOperand(OperandNo).getImm() == 0 && 58 "ISel should set p2align operands to 0"); 59 assert(MI.hasOneMemOperand() && 60 "Load and store instructions have exactly one mem operand"); 61 assert((*MI.memoperands_begin())->getSize() == 62 (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) && 63 "Default p2align value should be natural"); 64 assert(MI.getDesc().operands()[OperandNo].OperandType == 65 WebAssembly::OPERAND_P2ALIGN && 66 "Load and store instructions should have a p2align operand"); 67 uint64_t P2Align = Log2((*MI.memoperands_begin())->getAlign()); 68 69 // WebAssembly does not currently support supernatural alignment. 70 P2Align = std::min(P2Align, 71 uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); 72 73 MI.getOperand(OperandNo).setImm(P2Align); 74 } 75 76 bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { 77 LLVM_DEBUG({ 78 dbgs() << "********** Set p2align Operands **********\n" 79 << "********** Function: " << MF.getName() << '\n'; 80 }); 81 82 bool Changed = false; 83 84 for (auto &MBB : MF) { 85 for (auto &MI : MBB) { 86 int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx( 87 MI.getOpcode(), WebAssembly::OpName::p2align); 88 if (P2AlignOpNum != -1) { 89 rewriteP2Align(MI, P2AlignOpNum); 90 Changed = true; 91 } 92 } 93 } 94 95 return Changed; 96 } 97