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 "MCTargetDesc/WebAssemblyMCTargetDesc.h" 16 #include "WebAssembly.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 FunctionPass *llvm::createWebAssemblySetP2AlignOperands() { 50 return new WebAssemblySetP2AlignOperands(); 51 } 52 53 static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) { 54 assert(MI.getOperand(OperandNo).getImm() == 0 && 55 "ISel should set p2align operands to 0"); 56 assert(MI.hasOneMemOperand() && 57 "Load and store instructions have exactly one mem operand"); 58 assert((*MI.memoperands_begin())->getSize() == 59 (UINT64_C(1) 60 << WebAssembly::GetDefaultP2Align(MI.getOpcode())) && 61 "Default p2align value should be natural"); 62 assert(MI.getDesc().OpInfo[OperandNo].OperandType == 63 WebAssembly::OPERAND_P2ALIGN && 64 "Load and store instructions should have a p2align operand"); 65 uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); 66 67 // WebAssembly does not currently support supernatural alignment. 68 P2Align = std::min( 69 P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); 70 71 MI.getOperand(OperandNo).setImm(P2Align); 72 } 73 74 bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { 75 DEBUG({ 76 dbgs() << "********** Set p2align Operands **********\n" 77 << "********** Function: " << MF.getName() << '\n'; 78 }); 79 80 bool Changed = false; 81 82 for (auto &MBB : MF) { 83 for (auto &MI : MBB) { 84 switch (MI.getOpcode()) { 85 case WebAssembly::LOAD_I32: 86 case WebAssembly::LOAD_I64: 87 case WebAssembly::LOAD_F32: 88 case WebAssembly::LOAD_F64: 89 case WebAssembly::LOAD8_S_I32: 90 case WebAssembly::LOAD8_U_I32: 91 case WebAssembly::LOAD16_S_I32: 92 case WebAssembly::LOAD16_U_I32: 93 case WebAssembly::LOAD8_S_I64: 94 case WebAssembly::LOAD8_U_I64: 95 case WebAssembly::LOAD16_S_I64: 96 case WebAssembly::LOAD16_U_I64: 97 case WebAssembly::LOAD32_S_I64: 98 case WebAssembly::LOAD32_U_I64: 99 case WebAssembly::ATOMIC_LOAD_I32: 100 case WebAssembly::ATOMIC_LOAD8_U_I32: 101 case WebAssembly::ATOMIC_LOAD16_U_I32: 102 case WebAssembly::ATOMIC_LOAD_I64: 103 case WebAssembly::ATOMIC_LOAD8_U_I64: 104 case WebAssembly::ATOMIC_LOAD16_U_I64: 105 case WebAssembly::ATOMIC_LOAD32_U_I64: 106 RewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo); 107 break; 108 case WebAssembly::STORE_I32: 109 case WebAssembly::STORE_I64: 110 case WebAssembly::STORE_F32: 111 case WebAssembly::STORE_F64: 112 case WebAssembly::STORE8_I32: 113 case WebAssembly::STORE16_I32: 114 case WebAssembly::STORE8_I64: 115 case WebAssembly::STORE16_I64: 116 case WebAssembly::STORE32_I64: 117 RewriteP2Align(MI, WebAssembly::StoreP2AlignOperandNo); 118 break; 119 default: 120 break; 121 } 122 } 123 } 124 125 return Changed; 126 } 127