Path: blob/main/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerBrUnless.cpp
35266 views
//===-- WebAssemblyLowerBrUnless.cpp - Lower br_unless --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file lowers br_unless into br_if with an inverted condition.10///11/// br_unless is not currently in the spec, but it's very convenient for LLVM12/// to use. This pass allows LLVM to use it, for now.13///14//===----------------------------------------------------------------------===//1516#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"17#include "WebAssembly.h"18#include "WebAssemblyMachineFunctionInfo.h"19#include "WebAssemblySubtarget.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/Support/Debug.h"23#include "llvm/Support/raw_ostream.h"24using namespace llvm;2526#define DEBUG_TYPE "wasm-lower-br_unless"2728namespace {29class WebAssemblyLowerBrUnless final : public MachineFunctionPass {30StringRef getPassName() const override {31return "WebAssembly Lower br_unless";32}3334void getAnalysisUsage(AnalysisUsage &AU) const override {35AU.setPreservesCFG();36MachineFunctionPass::getAnalysisUsage(AU);37}3839bool runOnMachineFunction(MachineFunction &MF) override;4041public:42static char ID; // Pass identification, replacement for typeid43WebAssemblyLowerBrUnless() : MachineFunctionPass(ID) {}44};45} // end anonymous namespace4647char WebAssemblyLowerBrUnless::ID = 0;48INITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE,49"Lowers br_unless into inverted br_if", false, false)5051FunctionPass *llvm::createWebAssemblyLowerBrUnless() {52return new WebAssemblyLowerBrUnless();53}5455bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {56LLVM_DEBUG(dbgs() << "********** Lowering br_unless **********\n"57"********** Function: "58<< MF.getName() << '\n');5960auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();61const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();62auto &MRI = MF.getRegInfo();6364for (auto &MBB : MF) {65for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {66if (MI.getOpcode() != WebAssembly::BR_UNLESS)67continue;6869Register Cond = MI.getOperand(1).getReg();70bool Inverted = false;7172// Attempt to invert the condition in place.73if (MFI.isVRegStackified(Cond)) {74assert(MRI.hasOneDef(Cond));75MachineInstr *Def = MRI.getVRegDef(Cond);76switch (Def->getOpcode()) {77using namespace WebAssembly;78case EQ_I32:79Def->setDesc(TII.get(NE_I32));80Inverted = true;81break;82case NE_I32:83Def->setDesc(TII.get(EQ_I32));84Inverted = true;85break;86case GT_S_I32:87Def->setDesc(TII.get(LE_S_I32));88Inverted = true;89break;90case GE_S_I32:91Def->setDesc(TII.get(LT_S_I32));92Inverted = true;93break;94case LT_S_I32:95Def->setDesc(TII.get(GE_S_I32));96Inverted = true;97break;98case LE_S_I32:99Def->setDesc(TII.get(GT_S_I32));100Inverted = true;101break;102case GT_U_I32:103Def->setDesc(TII.get(LE_U_I32));104Inverted = true;105break;106case GE_U_I32:107Def->setDesc(TII.get(LT_U_I32));108Inverted = true;109break;110case LT_U_I32:111Def->setDesc(TII.get(GE_U_I32));112Inverted = true;113break;114case LE_U_I32:115Def->setDesc(TII.get(GT_U_I32));116Inverted = true;117break;118case EQ_I64:119Def->setDesc(TII.get(NE_I64));120Inverted = true;121break;122case NE_I64:123Def->setDesc(TII.get(EQ_I64));124Inverted = true;125break;126case GT_S_I64:127Def->setDesc(TII.get(LE_S_I64));128Inverted = true;129break;130case GE_S_I64:131Def->setDesc(TII.get(LT_S_I64));132Inverted = true;133break;134case LT_S_I64:135Def->setDesc(TII.get(GE_S_I64));136Inverted = true;137break;138case LE_S_I64:139Def->setDesc(TII.get(GT_S_I64));140Inverted = true;141break;142case GT_U_I64:143Def->setDesc(TII.get(LE_U_I64));144Inverted = true;145break;146case GE_U_I64:147Def->setDesc(TII.get(LT_U_I64));148Inverted = true;149break;150case LT_U_I64:151Def->setDesc(TII.get(GE_U_I64));152Inverted = true;153break;154case LE_U_I64:155Def->setDesc(TII.get(GT_U_I64));156Inverted = true;157break;158case EQ_F32:159Def->setDesc(TII.get(NE_F32));160Inverted = true;161break;162case NE_F32:163Def->setDesc(TII.get(EQ_F32));164Inverted = true;165break;166case EQ_F64:167Def->setDesc(TII.get(NE_F64));168Inverted = true;169break;170case NE_F64:171Def->setDesc(TII.get(EQ_F64));172Inverted = true;173break;174case EQZ_I32: {175// Invert an eqz by replacing it with its operand.176Cond = Def->getOperand(1).getReg();177Def->eraseFromParent();178Inverted = true;179break;180}181default:182break;183}184}185186// If we weren't able to invert the condition in place. Insert an187// instruction to invert it.188if (!Inverted) {189Register Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);190BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(WebAssembly::EQZ_I32), Tmp)191.addReg(Cond);192MFI.stackifyVReg(MRI, Tmp);193Cond = Tmp;194Inverted = true;195}196197// The br_unless condition has now been inverted. Insert a br_if and198// delete the br_unless.199assert(Inverted);200BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(WebAssembly::BR_IF))201.add(MI.getOperand(0))202.addReg(Cond);203MBB.erase(&MI);204}205}206207return true;208}209210211