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