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 "WebAssemblyMachineFunctionInfo.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<MachineBlockFrequencyInfo>(); 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().OpInfo[OperandNo].OperandType == 65 WebAssembly::OPERAND_P2ALIGN && 66 "Load and store instructions should have a p2align operand"); 67 uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); 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 switch (MI.getOpcode()) { 87 case WebAssembly::LOAD_I32: 88 case WebAssembly::LOAD_I64: 89 case WebAssembly::LOAD_F32: 90 case WebAssembly::LOAD_F64: 91 case WebAssembly::LOAD_v16i8: 92 case WebAssembly::LOAD_v8i16: 93 case WebAssembly::LOAD_v4i32: 94 case WebAssembly::LOAD_v2i64: 95 case WebAssembly::LOAD_v4f32: 96 case WebAssembly::LOAD_v2f64: 97 case WebAssembly::LOAD8_S_I32: 98 case WebAssembly::LOAD8_U_I32: 99 case WebAssembly::LOAD16_S_I32: 100 case WebAssembly::LOAD16_U_I32: 101 case WebAssembly::LOAD8_S_I64: 102 case WebAssembly::LOAD8_U_I64: 103 case WebAssembly::LOAD16_S_I64: 104 case WebAssembly::LOAD16_U_I64: 105 case WebAssembly::LOAD32_S_I64: 106 case WebAssembly::LOAD32_U_I64: 107 case WebAssembly::ATOMIC_LOAD_I32: 108 case WebAssembly::ATOMIC_LOAD8_U_I32: 109 case WebAssembly::ATOMIC_LOAD16_U_I32: 110 case WebAssembly::ATOMIC_LOAD_I64: 111 case WebAssembly::ATOMIC_LOAD8_U_I64: 112 case WebAssembly::ATOMIC_LOAD16_U_I64: 113 case WebAssembly::ATOMIC_LOAD32_U_I64: 114 case WebAssembly::ATOMIC_RMW8_U_ADD_I32: 115 case WebAssembly::ATOMIC_RMW8_U_ADD_I64: 116 case WebAssembly::ATOMIC_RMW8_U_SUB_I32: 117 case WebAssembly::ATOMIC_RMW8_U_SUB_I64: 118 case WebAssembly::ATOMIC_RMW8_U_AND_I32: 119 case WebAssembly::ATOMIC_RMW8_U_AND_I64: 120 case WebAssembly::ATOMIC_RMW8_U_OR_I32: 121 case WebAssembly::ATOMIC_RMW8_U_OR_I64: 122 case WebAssembly::ATOMIC_RMW8_U_XOR_I32: 123 case WebAssembly::ATOMIC_RMW8_U_XOR_I64: 124 case WebAssembly::ATOMIC_RMW8_U_XCHG_I32: 125 case WebAssembly::ATOMIC_RMW8_U_XCHG_I64: 126 case WebAssembly::ATOMIC_RMW8_U_CMPXCHG_I32: 127 case WebAssembly::ATOMIC_RMW8_U_CMPXCHG_I64: 128 case WebAssembly::ATOMIC_RMW16_U_ADD_I32: 129 case WebAssembly::ATOMIC_RMW16_U_ADD_I64: 130 case WebAssembly::ATOMIC_RMW16_U_SUB_I32: 131 case WebAssembly::ATOMIC_RMW16_U_SUB_I64: 132 case WebAssembly::ATOMIC_RMW16_U_AND_I32: 133 case WebAssembly::ATOMIC_RMW16_U_AND_I64: 134 case WebAssembly::ATOMIC_RMW16_U_OR_I32: 135 case WebAssembly::ATOMIC_RMW16_U_OR_I64: 136 case WebAssembly::ATOMIC_RMW16_U_XOR_I32: 137 case WebAssembly::ATOMIC_RMW16_U_XOR_I64: 138 case WebAssembly::ATOMIC_RMW16_U_XCHG_I32: 139 case WebAssembly::ATOMIC_RMW16_U_XCHG_I64: 140 case WebAssembly::ATOMIC_RMW16_U_CMPXCHG_I32: 141 case WebAssembly::ATOMIC_RMW16_U_CMPXCHG_I64: 142 case WebAssembly::ATOMIC_RMW_ADD_I32: 143 case WebAssembly::ATOMIC_RMW32_U_ADD_I64: 144 case WebAssembly::ATOMIC_RMW_SUB_I32: 145 case WebAssembly::ATOMIC_RMW32_U_SUB_I64: 146 case WebAssembly::ATOMIC_RMW_AND_I32: 147 case WebAssembly::ATOMIC_RMW32_U_AND_I64: 148 case WebAssembly::ATOMIC_RMW_OR_I32: 149 case WebAssembly::ATOMIC_RMW32_U_OR_I64: 150 case WebAssembly::ATOMIC_RMW_XOR_I32: 151 case WebAssembly::ATOMIC_RMW32_U_XOR_I64: 152 case WebAssembly::ATOMIC_RMW_XCHG_I32: 153 case WebAssembly::ATOMIC_RMW32_U_XCHG_I64: 154 case WebAssembly::ATOMIC_RMW_CMPXCHG_I32: 155 case WebAssembly::ATOMIC_RMW32_U_CMPXCHG_I64: 156 case WebAssembly::ATOMIC_RMW_ADD_I64: 157 case WebAssembly::ATOMIC_RMW_SUB_I64: 158 case WebAssembly::ATOMIC_RMW_AND_I64: 159 case WebAssembly::ATOMIC_RMW_OR_I64: 160 case WebAssembly::ATOMIC_RMW_XOR_I64: 161 case WebAssembly::ATOMIC_RMW_XCHG_I64: 162 case WebAssembly::ATOMIC_RMW_CMPXCHG_I64: 163 case WebAssembly::ATOMIC_NOTIFY: 164 case WebAssembly::ATOMIC_WAIT_I32: 165 case WebAssembly::ATOMIC_WAIT_I64: 166 RewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo); 167 break; 168 case WebAssembly::STORE_I32: 169 case WebAssembly::STORE_I64: 170 case WebAssembly::STORE_F32: 171 case WebAssembly::STORE_F64: 172 case WebAssembly::STORE_v16i8: 173 case WebAssembly::STORE_v8i16: 174 case WebAssembly::STORE_v4i32: 175 case WebAssembly::STORE_v2i64: 176 case WebAssembly::STORE_v4f32: 177 case WebAssembly::STORE_v2f64: 178 case WebAssembly::STORE8_I32: 179 case WebAssembly::STORE16_I32: 180 case WebAssembly::STORE8_I64: 181 case WebAssembly::STORE16_I64: 182 case WebAssembly::STORE32_I64: 183 case WebAssembly::ATOMIC_STORE_I32: 184 case WebAssembly::ATOMIC_STORE8_I32: 185 case WebAssembly::ATOMIC_STORE16_I32: 186 case WebAssembly::ATOMIC_STORE_I64: 187 case WebAssembly::ATOMIC_STORE8_I64: 188 case WebAssembly::ATOMIC_STORE16_I64: 189 case WebAssembly::ATOMIC_STORE32_I64: 190 RewriteP2Align(MI, WebAssembly::StoreP2AlignOperandNo); 191 break; 192 default: 193 break; 194 } 195 } 196 } 197 198 return Changed; 199 } 200