1//=- WebAssemblySetP2AlignOperands.cpp - Set alignments on loads and stores -=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// \brief This file sets the p2align operands on load and store instructions. 12/// 13//===----------------------------------------------------------------------===// 14 15#include "WebAssembly.h" 16#include "MCTargetDesc/WebAssemblyMCTargetDesc.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" 23using namespace llvm; 24 25#define DEBUG_TYPE "wasm-set-p2align-operands" 26 27namespace { 28class WebAssemblySetP2AlignOperands final : public MachineFunctionPass { 29public: 30 static char ID; // Pass identification, replacement for typeid 31 WebAssemblySetP2AlignOperands() : MachineFunctionPass(ID) {} 32 33 const char *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 48char WebAssemblySetP2AlignOperands::ID = 0; 49FunctionPass *llvm::createWebAssemblySetP2AlignOperands() { 50 return new WebAssemblySetP2AlignOperands(); 51} 52 53bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { 54 DEBUG({ 55 dbgs() << "********** Set p2align Operands **********\n" 56 << "********** Function: " << MF.getName() << '\n'; 57 }); 58 59 bool Changed = false; 60 61 for (auto &MBB : MF) { 62 for (auto &MI : MBB) { 63 switch (MI.getOpcode()) { 64 case WebAssembly::LOAD_I32: 65 case WebAssembly::LOAD_I64: 66 case WebAssembly::LOAD_F32: 67 case WebAssembly::LOAD_F64: 68 case WebAssembly::LOAD8_S_I32: 69 case WebAssembly::LOAD8_U_I32: 70 case WebAssembly::LOAD16_S_I32: 71 case WebAssembly::LOAD16_U_I32: 72 case WebAssembly::LOAD8_S_I64: 73 case WebAssembly::LOAD8_U_I64: 74 case WebAssembly::LOAD16_S_I64: 75 case WebAssembly::LOAD16_U_I64: 76 case WebAssembly::LOAD32_S_I64: 77 case WebAssembly::LOAD32_U_I64: 78 case WebAssembly::STORE_I32: 79 case WebAssembly::STORE_I64: 80 case WebAssembly::STORE_F32: 81 case WebAssembly::STORE_F64: 82 case WebAssembly::STORE8_I32: 83 case WebAssembly::STORE16_I32: 84 case WebAssembly::STORE8_I64: 85 case WebAssembly::STORE16_I64: 86 case WebAssembly::STORE32_I64: { 87 assert(MI.getOperand(3).getImm() == 0 && 88 "ISel should set p2align operands to 0"); 89 assert(MI.hasOneMemOperand() && 90 "Load and store instructions have exactly one mem operand"); 91 assert((*MI.memoperands_begin())->getSize() == 92 (UINT64_C(1) 93 << WebAssembly::GetDefaultP2Align(MI.getOpcode())) && 94 "Default p2align value should be natural"); 95 assert(MI.getDesc().OpInfo[3].OperandType == 96 WebAssembly::OPERAND_P2ALIGN && 97 "Load and store instructions should have a p2align operand"); 98 uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); 99 100 // WebAssembly does not currently support supernatural alignment. 101 P2Align = std::min( 102 P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); 103 104 MI.getOperand(3).setImm(P2Align); 105 break; 106 } 107 default: 108 break; 109 } 110 } 111 } 112 113 return Changed; 114} 115