WebAssemblyLowerBrUnless.cpp revision 344779
177218Sphk//===-- WebAssemblyLowerBrUnless.cpp - Lower br_unless --------------------===//
277218Sphk//
377218Sphk//                     The LLVM Compiler Infrastructure
477218Sphk//
577218Sphk// This file is distributed under the University of Illinois Open Source
677218Sphk// License. See LICENSE.TXT for details.
777218Sphk//
877218Sphk//===----------------------------------------------------------------------===//
977218Sphk///
1077218Sphk/// \file
1177218Sphk/// This file lowers br_unless into br_if with an inverted condition.
1291454Sbrooks///
1391454Sbrooks/// br_unless is not currently in the spec, but it's very convenient for LLVM
1477218Sphk/// to use. This pass allows LLVM to use it, for now.
1577218Sphk///
1677218Sphk//===----------------------------------------------------------------------===//
1777218Sphk
1877218Sphk#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1977218Sphk#include "WebAssembly.h"
2077218Sphk#include "WebAssemblyMachineFunctionInfo.h"
2177218Sphk#include "WebAssemblySubtarget.h"
2277218Sphk#include "llvm/CodeGen/MachineFunctionPass.h"
2377218Sphk#include "llvm/CodeGen/MachineInstrBuilder.h"
2477218Sphk#include "llvm/Support/Debug.h"
2577218Sphk#include "llvm/Support/raw_ostream.h"
2677218Sphkusing namespace llvm;
2777218Sphk
2877218Sphk#define DEBUG_TYPE "wasm-lower-br_unless"
2977218Sphk
3077218Sphknamespace {
3177218Sphkclass WebAssemblyLowerBrUnless final : public MachineFunctionPass {
3277218Sphk  StringRef getPassName() const override {
3377218Sphk    return "WebAssembly Lower br_unless";
3477218Sphk  }
3577218Sphk
3677218Sphk  void getAnalysisUsage(AnalysisUsage &AU) const override {
3777218Sphk    AU.setPreservesCFG();
3877218Sphk    MachineFunctionPass::getAnalysisUsage(AU);
3977218Sphk  }
4077218Sphk
4177218Sphk  bool runOnMachineFunction(MachineFunction &MF) override;
4277218Sphk
4377218Sphkpublic:
4477218Sphk  static char ID; // Pass identification, replacement for typeid
4577218Sphk  WebAssemblyLowerBrUnless() : MachineFunctionPass(ID) {}
4677218Sphk};
4777218Sphk} // end anonymous namespace
4877218Sphk
4977218Sphkchar WebAssemblyLowerBrUnless::ID = 0;
5077218SphkINITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE,
5177218Sphk                "Lowers br_unless into inverted br_if", false, false)
5277218Sphk
5377218SphkFunctionPass *llvm::createWebAssemblyLowerBrUnless() {
5477218Sphk  return new WebAssemblyLowerBrUnless();
5577218Sphk}
5677218Sphk
5777218Sphkbool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
5877218Sphk  LLVM_DEBUG(dbgs() << "********** Lowering br_unless **********\n"
5977218Sphk                       "********** Function: "
6077218Sphk                    << MF.getName() << '\n');
6177218Sphk
6277218Sphk  auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
6377218Sphk  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
6477218Sphk  auto &MRI = MF.getRegInfo();
6577218Sphk
6677218Sphk  for (auto &MBB : MF) {
6777218Sphk    for (auto MII = MBB.begin(); MII != MBB.end();) {
6877218Sphk      MachineInstr *MI = &*MII++;
6977218Sphk      if (MI->getOpcode() != WebAssembly::BR_UNLESS)
7077218Sphk        continue;
7177218Sphk
7277218Sphk      unsigned Cond = MI->getOperand(1).getReg();
7377218Sphk      bool Inverted = false;
7477218Sphk
7577218Sphk      // Attempt to invert the condition in place.
7677218Sphk      if (MFI.isVRegStackified(Cond)) {
77138593Ssam        assert(MRI.hasOneDef(Cond));
7877218Sphk        MachineInstr *Def = MRI.getVRegDef(Cond);
79138593Ssam        switch (Def->getOpcode()) {
80116957Ssam          using namespace WebAssembly;
81120178Ssam        case EQ_I32:
82116957Ssam          Def->setDesc(TII.get(NE_I32));
8377218Sphk          Inverted = true;
8477218Sphk          break;
8577218Sphk        case NE_I32:
8677218Sphk          Def->setDesc(TII.get(EQ_I32));
8777218Sphk          Inverted = true;
88146873Sjhb          break;
8977218Sphk        case GT_S_I32:
9077218Sphk          Def->setDesc(TII.get(LE_S_I32));
9177218Sphk          Inverted = true;
9277218Sphk          break;
9377218Sphk        case GE_S_I32:
9477218Sphk          Def->setDesc(TII.get(LT_S_I32));
9577218Sphk          Inverted = true;
9677218Sphk          break;
9777218Sphk        case LT_S_I32:
9877218Sphk          Def->setDesc(TII.get(GE_S_I32));
9977218Sphk          Inverted = true;
10077218Sphk          break;
101138593Ssam        case LE_S_I32:
102138593Ssam          Def->setDesc(TII.get(GT_S_I32));
103138593Ssam          Inverted = true;
104138593Ssam          break;
105138593Ssam        case GT_U_I32:
106138593Ssam          Def->setDesc(TII.get(LE_U_I32));
107138593Ssam          Inverted = true;
108138593Ssam          break;
10977218Sphk        case GE_U_I32:
11077218Sphk          Def->setDesc(TII.get(LT_U_I32));
11177218Sphk          Inverted = true;
11277218Sphk          break;
113151883Sbrooks        case LT_U_I32:
11477218Sphk          Def->setDesc(TII.get(GE_U_I32));
11577218Sphk          Inverted = true;
116121827Sbrooks          break;
11788748Sambrisko        case LE_U_I32:
11888748Sambrisko          Def->setDesc(TII.get(GT_U_I32));
11988748Sambrisko          Inverted = true;
12088748Sambrisko          break;
12177218Sphk        case EQ_I64:
12277218Sphk          Def->setDesc(TII.get(NE_I64));
12377218Sphk          Inverted = true;
124151883Sbrooks          break;
125151883Sbrooks        case NE_I64:
12677218Sphk          Def->setDesc(TII.get(EQ_I64));
12777218Sphk          Inverted = true;
12877218Sphk          break;
12977218Sphk        case GT_S_I64:
130138593Ssam          Def->setDesc(TII.get(LE_S_I64));
13177218Sphk          Inverted = true;
13277218Sphk          break;
13377218Sphk        case GE_S_I64:
13477218Sphk          Def->setDesc(TII.get(LT_S_I64));
13577218Sphk          Inverted = true;
13677218Sphk          break;
13777218Sphk        case LT_S_I64:
13877218Sphk          Def->setDesc(TII.get(GE_S_I64));
13977218Sphk          Inverted = true;
14077218Sphk          break;
14177218Sphk        case LE_S_I64:
14277218Sphk          Def->setDesc(TII.get(GT_S_I64));
143138593Ssam          Inverted = true;
144138593Ssam          break;
145138593Ssam        case GT_U_I64:
146138593Ssam          Def->setDesc(TII.get(LE_U_I64));
147138593Ssam          Inverted = true;
148138593Ssam          break;
149138593Ssam        case GE_U_I64:
150138593Ssam          Def->setDesc(TII.get(LT_U_I64));
151138593Ssam          Inverted = true;
152138593Ssam          break;
153138593Ssam        case LT_U_I64:
154138593Ssam          Def->setDesc(TII.get(GE_U_I64));
155138593Ssam          Inverted = true;
156138593Ssam          break;
157138593Ssam        case LE_U_I64:
158138593Ssam          Def->setDesc(TII.get(GT_U_I64));
159138593Ssam          Inverted = true;
160138593Ssam          break;
161138593Ssam        case EQ_F32:
162138593Ssam          Def->setDesc(TII.get(NE_F32));
163138593Ssam          Inverted = true;
164138593Ssam          break;
165138593Ssam        case NE_F32:
166138593Ssam          Def->setDesc(TII.get(EQ_F32));
167138593Ssam          Inverted = true;
168138593Ssam          break;
169138593Ssam        case EQ_F64:
170138593Ssam          Def->setDesc(TII.get(NE_F64));
171138593Ssam          Inverted = true;
172138593Ssam          break;
173138593Ssam        case NE_F64:
17477218Sphk          Def->setDesc(TII.get(EQ_F64));
17577218Sphk          Inverted = true;
176138593Ssam          break;
177138593Ssam        case EQZ_I32: {
178138593Ssam          // Invert an eqz by replacing it with its operand.
179138593Ssam          Cond = Def->getOperand(1).getReg();
180138593Ssam          Def->eraseFromParent();
181138593Ssam          Inverted = true;
182116957Ssam          break;
18377218Sphk        }
18477218Sphk        default:
185138593Ssam          break;
18677218Sphk        }
18777218Sphk      }
18877218Sphk
18977218Sphk      // If we weren't able to invert the condition in place. Insert an
19091454Sbrooks      // instruction to invert it.
19177218Sphk      if (!Inverted) {
19291454Sbrooks        unsigned Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
19377218Sphk        BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::EQZ_I32), Tmp)
19491454Sbrooks            .addReg(Cond);
19577218Sphk        MFI.stackifyVReg(Tmp);
196138593Ssam        Cond = Tmp;
197138593Ssam        Inverted = true;
198138593Ssam      }
199138593Ssam
20077218Sphk      // The br_unless condition has now been inverted. Insert a br_if and
201150708Sru      // delete the br_unless.
20277218Sphk      assert(Inverted);
20377218Sphk      BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::BR_IF))
20477218Sphk          .add(MI->getOperand(0))
20577218Sphk          .addReg(Cond);
20677218Sphk      MBB.erase(MI);
207138593Ssam    }
20877218Sphk  }
20977218Sphk
21077218Sphk  return true;
21177218Sphk}
21291454Sbrooks