LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyLowerBrUnless.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 45 105 42.9 %
Date: 2018-10-20 13:21:21 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- WebAssemblyLowerBrUnless.cpp - Lower br_unless --------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : ///
      10             : /// \file
      11             : /// This file lowers br_unless into br_if with an inverted condition.
      12             : ///
      13             : /// br_unless is not currently in the spec, but it's very convenient for LLVM
      14             : /// to use. This pass allows LLVM to use it, for now.
      15             : ///
      16             : //===----------------------------------------------------------------------===//
      17             : 
      18             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      19             : #include "WebAssembly.h"
      20             : #include "WebAssemblyMachineFunctionInfo.h"
      21             : #include "WebAssemblySubtarget.h"
      22             : #include "llvm/CodeGen/MachineFunctionPass.h"
      23             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      24             : #include "llvm/Support/Debug.h"
      25             : #include "llvm/Support/raw_ostream.h"
      26             : using namespace llvm;
      27             : 
      28             : #define DEBUG_TYPE "wasm-lower-br_unless"
      29             : 
      30             : namespace {
      31             : class WebAssemblyLowerBrUnless final : public MachineFunctionPass {
      32         304 :   StringRef getPassName() const override {
      33         304 :     return "WebAssembly Lower br_unless";
      34             :   }
      35             : 
      36         304 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      37         304 :     AU.setPreservesCFG();
      38         304 :     MachineFunctionPass::getAnalysisUsage(AU);
      39         304 :   }
      40             : 
      41             :   bool runOnMachineFunction(MachineFunction &MF) override;
      42             : 
      43             : public:
      44             :   static char ID; // Pass identification, replacement for typeid
      45         305 :   WebAssemblyLowerBrUnless() : MachineFunctionPass(ID) {}
      46             : };
      47             : } // end anonymous namespace
      48             : 
      49             : char WebAssemblyLowerBrUnless::ID = 0;
      50      199030 : INITIALIZE_PASS(WebAssemblyLowerBrUnless, DEBUG_TYPE,
      51             :                 "Lowers br_unless into inverted br_if", false, false)
      52             : 
      53         305 : FunctionPass *llvm::createWebAssemblyLowerBrUnless() {
      54         305 :   return new WebAssemblyLowerBrUnless();
      55             : }
      56             : 
      57        2982 : bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
      58             :   LLVM_DEBUG(dbgs() << "********** Lowering br_unless **********\n"
      59             :                        "********** Function: "
      60             :                     << MF.getName() << '\n');
      61             : 
      62             :   auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
      63        2982 :   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
      64        2982 :   auto &MRI = MF.getRegInfo();
      65             : 
      66        6532 :   for (auto &MBB : MF) {
      67       35222 :     for (auto MII = MBB.begin(); MII != MBB.end();) {
      68             :       MachineInstr *MI = &*MII++;
      69       63344 :       if (MI->getOpcode() != WebAssembly::BR_UNLESS)
      70             :         continue;
      71             : 
      72          85 :       unsigned Cond = MI->getOperand(1).getReg();
      73             :       bool Inverted = false;
      74             : 
      75             :       // Attempt to invert the condition in place.
      76          82 :       if (MFI.isVRegStackified(Cond)) {
      77             :         assert(MRI.hasOneDef(Cond));
      78          59 :         MachineInstr *Def = MRI.getVRegDef(Cond);
      79         118 :         switch (Def->getOpcode()) {
      80             :           using namespace WebAssembly;
      81           1 :         case EQ_I32:
      82           1 :           Def->setDesc(TII.get(NE_I32));
      83             :           Inverted = true;
      84           1 :           break;
      85           0 :         case NE_I32:
      86           0 :           Def->setDesc(TII.get(EQ_I32));
      87             :           Inverted = true;
      88           0 :           break;
      89           1 :         case GT_S_I32:
      90           1 :           Def->setDesc(TII.get(LE_S_I32));
      91             :           Inverted = true;
      92           1 :           break;
      93           0 :         case GE_S_I32:
      94           0 :           Def->setDesc(TII.get(LT_S_I32));
      95             :           Inverted = true;
      96           0 :           break;
      97           4 :         case LT_S_I32:
      98           4 :           Def->setDesc(TII.get(GE_S_I32));
      99             :           Inverted = true;
     100           4 :           break;
     101           0 :         case LE_S_I32:
     102           0 :           Def->setDesc(TII.get(GT_S_I32));
     103             :           Inverted = true;
     104           0 :           break;
     105           0 :         case GT_U_I32:
     106           0 :           Def->setDesc(TII.get(LE_U_I32));
     107             :           Inverted = true;
     108           0 :           break;
     109           0 :         case GE_U_I32:
     110           0 :           Def->setDesc(TII.get(LT_U_I32));
     111             :           Inverted = true;
     112           0 :           break;
     113           2 :         case LT_U_I32:
     114           2 :           Def->setDesc(TII.get(GE_U_I32));
     115             :           Inverted = true;
     116           2 :           break;
     117           0 :         case LE_U_I32:
     118           0 :           Def->setDesc(TII.get(GT_U_I32));
     119             :           Inverted = true;
     120           0 :           break;
     121           0 :         case EQ_I64:
     122           0 :           Def->setDesc(TII.get(NE_I64));
     123             :           Inverted = true;
     124           0 :           break;
     125           0 :         case NE_I64:
     126           0 :           Def->setDesc(TII.get(EQ_I64));
     127             :           Inverted = true;
     128           0 :           break;
     129           0 :         case GT_S_I64:
     130           0 :           Def->setDesc(TII.get(LE_S_I64));
     131             :           Inverted = true;
     132           0 :           break;
     133           0 :         case GE_S_I64:
     134           0 :           Def->setDesc(TII.get(LT_S_I64));
     135             :           Inverted = true;
     136           0 :           break;
     137           0 :         case LT_S_I64:
     138           0 :           Def->setDesc(TII.get(GE_S_I64));
     139             :           Inverted = true;
     140           0 :           break;
     141           0 :         case LE_S_I64:
     142           0 :           Def->setDesc(TII.get(GT_S_I64));
     143             :           Inverted = true;
     144           0 :           break;
     145           0 :         case GT_U_I64:
     146           0 :           Def->setDesc(TII.get(LE_U_I64));
     147             :           Inverted = true;
     148           0 :           break;
     149           0 :         case GE_U_I64:
     150           0 :           Def->setDesc(TII.get(LT_U_I64));
     151             :           Inverted = true;
     152           0 :           break;
     153           0 :         case LT_U_I64:
     154           0 :           Def->setDesc(TII.get(GE_U_I64));
     155             :           Inverted = true;
     156           0 :           break;
     157           0 :         case LE_U_I64:
     158           0 :           Def->setDesc(TII.get(GT_U_I64));
     159             :           Inverted = true;
     160           0 :           break;
     161           0 :         case EQ_F32:
     162           0 :           Def->setDesc(TII.get(NE_F32));
     163             :           Inverted = true;
     164           0 :           break;
     165           0 :         case NE_F32:
     166           0 :           Def->setDesc(TII.get(EQ_F32));
     167             :           Inverted = true;
     168           0 :           break;
     169           0 :         case EQ_F64:
     170           0 :           Def->setDesc(TII.get(NE_F64));
     171             :           Inverted = true;
     172           0 :           break;
     173           0 :         case NE_F64:
     174           0 :           Def->setDesc(TII.get(EQ_F64));
     175             :           Inverted = true;
     176           0 :           break;
     177          24 :         case EQZ_I32: {
     178             :           // Invert an eqz by replacing it with its operand.
     179          24 :           Cond = Def->getOperand(1).getReg();
     180          24 :           Def->eraseFromParent();
     181             :           Inverted = true;
     182          24 :           break;
     183             :         }
     184             :         default:
     185             :           break;
     186             :         }
     187             :       }
     188             : 
     189             :       // If we weren't able to invert the condition in place. Insert an
     190             :       // instruction to invert it.
     191          85 :       if (!Inverted) {
     192          53 :         unsigned Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
     193          53 :         BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::EQZ_I32), Tmp)
     194          53 :             .addReg(Cond);
     195          53 :         MFI.stackifyVReg(Tmp);
     196             :         Cond = Tmp;
     197             :         Inverted = true;
     198             :       }
     199             : 
     200             :       // The br_unless condition has now been inverted. Insert a br_if and
     201             :       // delete the br_unless.
     202             :       assert(Inverted);
     203         170 :       BuildMI(MBB, MI, MI->getDebugLoc(), TII.get(WebAssembly::BR_IF))
     204          85 :           .add(MI->getOperand(0))
     205          85 :           .addReg(Cond);
     206             :       MBB.erase(MI);
     207             :     }
     208             :   }
     209             : 
     210        2982 :   return true;
     211             : }

Generated by: LCOV version 1.13