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 "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<MachineBlockFrequencyInfoWrapperPass>(); |
39 | AU.addPreservedID(ID&: 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().operands()[OperandNo].OperandType == |
65 | WebAssembly::OPERAND_P2ALIGN && |
66 | "Load and store instructions should have a p2align operand" ); |
67 | uint64_t P2Align = Log2(A: (*MI.memoperands_begin())->getAlign()); |
68 | |
69 | // WebAssembly does not currently support supernatural alignment. |
70 | P2Align = std::min(a: P2Align, |
71 | b: uint64_t(WebAssembly::GetDefaultP2Align(Opc: MI.getOpcode()))); |
72 | |
73 | MI.getOperand(i: 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 | int16_t P2AlignOpNum = WebAssembly::getNamedOperandIdx( |
87 | Opcode: MI.getOpcode(), Name: WebAssembly::OpName::p2align); |
88 | if (P2AlignOpNum != -1) { |
89 | rewriteP2Align(MI, OperandNo: P2AlignOpNum); |
90 | Changed = true; |
91 | } |
92 | } |
93 | } |
94 | |
95 | return Changed; |
96 | } |
97 | |