LLVM  14.0.0git
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) {
67  if (MI.getOpcode() != WebAssembly::BR_UNLESS)
68  continue;
69 
70  Register Cond = MI.getOperand(1).getReg();
71  bool Inverted = false;
72 
73  // Attempt to invert the condition in place.
74  if (MFI.isVRegStackified(Cond)) {
77  switch (Def->getOpcode()) {
78  using namespace WebAssembly;
79  case EQ_I32:
80  Def->setDesc(TII.get(NE_I32));
81  Inverted = true;
82  break;
83  case NE_I32:
84  Def->setDesc(TII.get(EQ_I32));
85  Inverted = true;
86  break;
87  case GT_S_I32:
88  Def->setDesc(TII.get(LE_S_I32));
89  Inverted = true;
90  break;
91  case GE_S_I32:
92  Def->setDesc(TII.get(LT_S_I32));
93  Inverted = true;
94  break;
95  case LT_S_I32:
96  Def->setDesc(TII.get(GE_S_I32));
97  Inverted = true;
98  break;
99  case LE_S_I32:
100  Def->setDesc(TII.get(GT_S_I32));
101  Inverted = true;
102  break;
103  case GT_U_I32:
104  Def->setDesc(TII.get(LE_U_I32));
105  Inverted = true;
106  break;
107  case GE_U_I32:
108  Def->setDesc(TII.get(LT_U_I32));
109  Inverted = true;
110  break;
111  case LT_U_I32:
112  Def->setDesc(TII.get(GE_U_I32));
113  Inverted = true;
114  break;
115  case LE_U_I32:
116  Def->setDesc(TII.get(GT_U_I32));
117  Inverted = true;
118  break;
119  case EQ_I64:
120  Def->setDesc(TII.get(NE_I64));
121  Inverted = true;
122  break;
123  case NE_I64:
124  Def->setDesc(TII.get(EQ_I64));
125  Inverted = true;
126  break;
127  case GT_S_I64:
128  Def->setDesc(TII.get(LE_S_I64));
129  Inverted = true;
130  break;
131  case GE_S_I64:
132  Def->setDesc(TII.get(LT_S_I64));
133  Inverted = true;
134  break;
135  case LT_S_I64:
136  Def->setDesc(TII.get(GE_S_I64));
137  Inverted = true;
138  break;
139  case LE_S_I64:
140  Def->setDesc(TII.get(GT_S_I64));
141  Inverted = true;
142  break;
143  case GT_U_I64:
144  Def->setDesc(TII.get(LE_U_I64));
145  Inverted = true;
146  break;
147  case GE_U_I64:
148  Def->setDesc(TII.get(LT_U_I64));
149  Inverted = true;
150  break;
151  case LT_U_I64:
152  Def->setDesc(TII.get(GE_U_I64));
153  Inverted = true;
154  break;
155  case LE_U_I64:
156  Def->setDesc(TII.get(GT_U_I64));
157  Inverted = true;
158  break;
159  case EQ_F32:
160  Def->setDesc(TII.get(NE_F32));
161  Inverted = true;
162  break;
163  case NE_F32:
164  Def->setDesc(TII.get(EQ_F32));
165  Inverted = true;
166  break;
167  case EQ_F64:
168  Def->setDesc(TII.get(NE_F64));
169  Inverted = true;
170  break;
171  case NE_F64:
172  Def->setDesc(TII.get(EQ_F64));
173  Inverted = true;
174  break;
175  case EQZ_I32: {
176  // Invert an eqz by replacing it with its operand.
177  Cond = Def->getOperand(1).getReg();
178  Def->eraseFromParent();
179  Inverted = true;
180  break;
181  }
182  default:
183  break;
184  }
185  }
186 
187  // If we weren't able to invert the condition in place. Insert an
188  // instruction to invert it.
189  if (!Inverted) {
190  Register Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
191  BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(WebAssembly::EQZ_I32), Tmp)
192  .addReg(Cond);
193  MFI.stackifyVReg(MRI, Tmp);
194  Cond = Tmp;
195  Inverted = true;
196  }
197 
198  // The br_unless condition has now been inverted. Insert a br_if and
199  // delete the br_unless.
200  assert(Inverted);
201  BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(WebAssembly::BR_IF))
202  .add(MI.getOperand(0))
203  .addReg(Cond);
204  MBB.erase(&MI);
205  }
206  }
207 
208  return true;
209 }
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
WebAssembly.h
llvm::MachineRegisterInfo::createVirtualRegister
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Definition: MachineRegisterInfo.cpp:158
llvm::MachineInstrBuilder::add
const MachineInstrBuilder & add(const MachineOperand &MO) const
Definition: MachineInstrBuilder.h:224
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::MachineBasicBlock::erase
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
Definition: MachineBasicBlock.cpp:1304
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:636
llvm::MachineFunction::getInfo
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Definition: MachineFunction.h:724
INITIALIZE_PASS
INITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE, "Lowers br_unless into inverted br_if", false, false) FunctionPass *llvm
Definition: WebAssemblyLowerBrUnless.cpp:49
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:129
llvm::MachineRegisterInfo::getVRegDef
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Definition: MachineRegisterInfo.cpp:400
WebAssemblyMCTargetDesc.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:626
DEBUG_TYPE
#define DEBUG_TYPE
Definition: WebAssemblyLowerBrUnless.cpp:27
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:576
MachineFunctionPass.h
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:541
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::WebAssemblyFunctionInfo
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
Definition: WebAssemblyMachineFunctionInfo.h:33
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition: MachineInstrBuilder.h:97
llvm::MachineRegisterInfo::hasOneDef
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
Definition: MachineRegisterInfo.h:444
WebAssemblyMachineFunctionInfo.h
llvm::MachineFunction
Definition: MachineFunction.h:230
Cond
SmallVector< MachineOperand, 4 > Cond
Definition: BasicBlockSections.cpp:179
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
WebAssemblySubtarget.h
MachineInstrBuilder.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
llvm::createWebAssemblyLowerBrUnless
FunctionPass * createWebAssemblyLowerBrUnless()
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
raw_ostream.h
Debug.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37