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<MachineBlockFrequencyInfoWrapperPass>(); |
40 | AU.addPreservedID(ID&: 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(A: (*MI.memoperands_begin())->getAlign()); |
69 | |
70 | // WebAssembly does not currently support supernatural alignment. |
71 | P2Align = std::min(a: P2Align, |
72 | b: uint64_t(WebAssembly::GetDefaultP2Align(Opc: MI.getOpcode()))); |
73 | |
74 | MI.getOperand(i: 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 | Opcode: MI.getOpcode(), NamedIndex: WebAssembly::OpName::p2align); |
89 | if (P2AlignOpNum != -1) { |
90 | rewriteP2Align(MI, OperandNo: P2AlignOpNum); |
91 | Changed = true; |
92 | } |
93 | } |
94 | } |
95 | |
96 | return Changed; |
97 | } |
98 | |