LLVM  10.0.0svn
WebAssemblyLowerBrUnless.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyLowerBrUnless.cpp - Lower br_unless --------------------===//
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 lowers br_unless into br_if with an inverted condition.
11 ///
12 /// br_unless is not currently in the spec, but it's very convenient for LLVM
13 /// to use. This pass allows LLVM to use it, for now.
14 ///
15 //===----------------------------------------------------------------------===//
16 
18 #include "WebAssembly.h"
20 #include "WebAssemblySubtarget.h"
23 #include "llvm/Support/Debug.h"
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "wasm-lower-br_unless"
28 
29 namespace {
30 class WebAssemblyLowerBrUnless final : public MachineFunctionPass {
31  StringRef getPassName() const override {
32  return "WebAssembly Lower br_unless";
33  }
34 
35  void getAnalysisUsage(AnalysisUsage &AU) const override {
36  AU.setPreservesCFG();
38  }
39 
40  bool runOnMachineFunction(MachineFunction &MF) override;
41 
42 public:
43  static char ID; // Pass identification, replacement for typeid
44  WebAssemblyLowerBrUnless() : MachineFunctionPass(ID) {}
45 };
46 } // end anonymous namespace
47 
49 INITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE,
50  "Lowers br_unless into inverted br_if", false, false)
51 
53  return new WebAssemblyLowerBrUnless();
54 }
55 
56 bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
57  LLVM_DEBUG(dbgs() << "********** Lowering br_unless **********\n"
58  "********** Function: "
59  << MF.getName() << '\n');
60 
61  auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
62  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
63  auto &MRI = MF.getRegInfo();
64 
65  for (auto &MBB : MF) {
66  for (auto MII = MBB.begin(); MII != MBB.end();) {
67  MachineInstr *MI = &*MII++;
68  if (MI->getOpcode() != WebAssembly::BR_UNLESS)
69  continue;
70 
71  Register Cond = MI->getOperand(1).getReg();
72  bool Inverted = false;
73 
74  // Attempt to invert the condition in place.
75  if (MFI.isVRegStackified(Cond)) {
76  assert(MRI.hasOneDef(Cond));
77  MachineInstr *Def = MRI.getVRegDef(Cond);
78  switch (Def->getOpcode()) {
79  using namespace WebAssembly;
80  case EQ_I32:
81  Def->setDesc(TII.get(NE_I32));
82  Inverted = true;
83  break;
84  case NE_I32:
85  Def->setDesc(TII.get(EQ_I32));
86  Inverted = true;
87  break;
88  case GT_S_I32:
89  Def->setDesc(TII.get(LE_S_I32));
90  Inverted = true;
91  break;
92  case GE_S_I32:
93  Def->setDesc(TII.get(LT_S_I32));
94  Inverted = true;
95  break;
96  case LT_S_I32:
97  Def->setDesc(TII.get(GE_S_I32));
98  Inverted = true;
99  break;
100  case LE_S_I32:
101  Def->setDesc(TII.get(GT_S_I32));
102  Inverted = true;
103  break;
104  case GT_U_I32:
105  Def->setDesc(TII.get(LE_U_I32));
106  Inverted = true;
107  break;
108  case GE_U_I32:
109  Def->setDesc(TII.get(LT_U_I32));
110  Inverted = true;
111  break;
112  case LT_U_I32:
113  Def->setDesc(TII.get(GE_U_I32));
114  Inverted = true;
115  break;
116  case LE_U_I32:
117  Def->setDesc(TII.get(GT_U_I32));
118  Inverted = true;
119  break;
120  case EQ_I64:
121  Def->setDesc(TII.get(NE_I64));
122  Inverted = true;
123  break;
124  case NE_I64:
125  Def->setDesc(TII.get(EQ_I64));
126  Inverted = true;
127  break;
128  case GT_S_I64:
129  Def->setDesc(TII.get(LE_S_I64));
130  Inverted = true;
131  break;
132  case GE_S_I64:
133  Def->setDesc(TII.get(LT_S_I64));
134  Inverted = true;
135  break;
136  case LT_S_I64:
137  Def->setDesc(TII.get(GE_S_I64));
138  Inverted = true;
139  break;
140  case LE_S_I64:
141  Def->setDesc(TII.get(GT_S_I64));
142  Inverted = true;
143  break;
144  case GT_U_I64:
145  Def->setDesc(TII.get(LE_U_I64));
146  Inverted = true;
147  break;
148  case GE_U_I64:
149  Def->setDesc(TII.get(LT_U_I64));
150  Inverted = true;
151  break;
152  case LT_U_I64:
153  Def->setDesc(TII.get(GE_U_I64));
154  Inverted = true;
155  break;
156  case LE_U_I64:
157  Def->setDesc(TII.get(GT_U_I64));
158  Inverted = true;
159  break;
160  case EQ_F32:
161  Def->setDesc(TII.get(NE_F32));
162  Inverted = true;
163  break;
164  case NE_F32:
165  Def->setDesc(TII.get(EQ_F32));
166  Inverted = true;
167  break;
168  case EQ_F64:
169  Def->setDesc(TII.get(NE_F64));
170  Inverted = true;
171  break;
172  case NE_F64:
173  Def->setDesc(TII.get(EQ_F64));
174  Inverted = true;
175  break;
176  case EQZ_I32: {
177  // Invert an eqz by replacing it with its operand.
178  Cond = Def->getOperand(1).getReg();
179  Def->eraseFromParent();
180  Inverted = true;
181  break;
182  }
183  default:
184  break;
185  }
186  }
187 
188  // If we weren't able to invert the condition in place. Insert an
189  // instruction to invert it.
190  if (!Inverted) {
191  Register Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
192  BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::EQZ_I32), Tmp)
193  .addReg(Cond);
194  MFI.stackifyVReg(Tmp);
195  Cond = Tmp;
196  Inverted = true;
197  }
198 
199  // The br_unless condition has now been inverted. Insert a br_if and
200  // delete the br_unless.
201  assert(Inverted);
202  BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::BR_IF))
203  .add(MI->getOperand(0))
204  .addReg(Cond);
205  MBB.erase(MI);
206  }
207  }
208 
209  return true;
210 }
FunctionPass * createWebAssemblyLowerBrUnless()
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:385
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
#define DEBUG_TYPE
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
This file declares the WebAssembly-specific subclass of TargetSubtarget.
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:215
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:301
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Representation of each machine instruction.
Definition: MachineInstr.h:64
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
INITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE, "Lowers br_unless into inverted br_if", false, false) FunctionPass *llvm
This file declares WebAssembly-specific per-machine-function information.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Register getReg() const
getReg - Returns the register number.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
Wrapper class representing virtual and physical registers.
Definition: Register.h:19