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