Home | History | Annotate | Download | only in WebAssembly
      1 //===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
      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 contains the WebAssembly implementation of the
     12 /// TargetInstrInfo class.
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "WebAssemblyInstrInfo.h"
     17 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
     18 #include "WebAssemblyMachineFunctionInfo.h"
     19 #include "WebAssemblySubtarget.h"
     20 #include "llvm/CodeGen/MachineFrameInfo.h"
     21 #include "llvm/CodeGen/MachineInstrBuilder.h"
     22 #include "llvm/CodeGen/MachineMemOperand.h"
     23 #include "llvm/CodeGen/MachineRegisterInfo.h"
     24 using namespace llvm;
     25 
     26 #define DEBUG_TYPE "wasm-instr-info"
     27 
     28 #define GET_INSTRINFO_CTOR_DTOR
     29 #include "WebAssemblyGenInstrInfo.inc"
     30 
     31 WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
     32     : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
     33                               WebAssembly::ADJCALLSTACKUP,
     34                               WebAssembly::CATCHRET),
     35       RI(STI.getTargetTriple()) {}
     36 
     37 bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
     38     const MachineInstr &MI, AliasAnalysis *AA) const {
     39   switch (MI.getOpcode()) {
     40   case WebAssembly::CONST_I32:
     41   case WebAssembly::CONST_I64:
     42   case WebAssembly::CONST_F32:
     43   case WebAssembly::CONST_F64:
     44     // isReallyTriviallyReMaterializableGeneric misses these because of the
     45     // ARGUMENTS implicit def, so we manualy override it here.
     46     return true;
     47   default:
     48     return false;
     49   }
     50 }
     51 
     52 void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     53                                        MachineBasicBlock::iterator I,
     54                                        const DebugLoc &DL, unsigned DestReg,
     55                                        unsigned SrcReg, bool KillSrc) const {
     56   // This method is called by post-RA expansion, which expects only pregs to
     57   // exist. However we need to handle both here.
     58   auto &MRI = MBB.getParent()->getRegInfo();
     59   const TargetRegisterClass *RC =
     60       TargetRegisterInfo::isVirtualRegister(DestReg)
     61           ? MRI.getRegClass(DestReg)
     62           : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
     63 
     64   unsigned CopyOpcode;
     65   if (RC == &WebAssembly::I32RegClass)
     66     CopyOpcode = WebAssembly::COPY_I32;
     67   else if (RC == &WebAssembly::I64RegClass)
     68     CopyOpcode = WebAssembly::COPY_I64;
     69   else if (RC == &WebAssembly::F32RegClass)
     70     CopyOpcode = WebAssembly::COPY_F32;
     71   else if (RC == &WebAssembly::F64RegClass)
     72     CopyOpcode = WebAssembly::COPY_F64;
     73   else
     74     llvm_unreachable("Unexpected register class");
     75 
     76   BuildMI(MBB, I, DL, get(CopyOpcode), DestReg)
     77       .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
     78 }
     79 
     80 MachineInstr *
     81 WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
     82                                              unsigned OpIdx1,
     83                                              unsigned OpIdx2) const {
     84   // If the operands are stackified, we can't reorder them.
     85   WebAssemblyFunctionInfo &MFI =
     86       *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
     87   if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
     88       MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))
     89     return nullptr;
     90 
     91   // Otherwise use the default implementation.
     92   return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
     93 }
     94 
     95 // Branch analysis.
     96 bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
     97                                          MachineBasicBlock *&TBB,
     98                                          MachineBasicBlock *&FBB,
     99                                          SmallVectorImpl<MachineOperand> &Cond,
    100                                          bool /*AllowModify*/) const {
    101   bool HaveCond = false;
    102   for (MachineInstr &MI : MBB.terminators()) {
    103     switch (MI.getOpcode()) {
    104     default:
    105       // Unhandled instruction; bail out.
    106       return true;
    107     case WebAssembly::BR_IF:
    108       if (HaveCond)
    109         return true;
    110       // If we're running after CFGStackify, we can't optimize further.
    111       if (!MI.getOperand(0).isMBB())
    112         return true;
    113       Cond.push_back(MachineOperand::CreateImm(true));
    114       Cond.push_back(MI.getOperand(1));
    115       TBB = MI.getOperand(0).getMBB();
    116       HaveCond = true;
    117       break;
    118     case WebAssembly::BR_UNLESS:
    119       if (HaveCond)
    120         return true;
    121       // If we're running after CFGStackify, we can't optimize further.
    122       if (!MI.getOperand(0).isMBB())
    123         return true;
    124       Cond.push_back(MachineOperand::CreateImm(false));
    125       Cond.push_back(MI.getOperand(1));
    126       TBB = MI.getOperand(0).getMBB();
    127       HaveCond = true;
    128       break;
    129     case WebAssembly::BR:
    130       // If we're running after CFGStackify, we can't optimize further.
    131       if (!MI.getOperand(0).isMBB())
    132         return true;
    133       if (!HaveCond)
    134         TBB = MI.getOperand(0).getMBB();
    135       else
    136         FBB = MI.getOperand(0).getMBB();
    137       break;
    138     }
    139     if (MI.isBarrier())
    140       break;
    141   }
    142 
    143   return false;
    144 }
    145 
    146 unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
    147                                             int *BytesRemoved) const {
    148   assert(!BytesRemoved && "code size not handled");
    149 
    150   MachineBasicBlock::instr_iterator I = MBB.instr_end();
    151   unsigned Count = 0;
    152 
    153   while (I != MBB.instr_begin()) {
    154     --I;
    155     if (I->isDebugInstr())
    156       continue;
    157     if (!I->isTerminator())
    158       break;
    159     // Remove the branch.
    160     I->eraseFromParent();
    161     I = MBB.instr_end();
    162     ++Count;
    163   }
    164 
    165   return Count;
    166 }
    167 
    168 unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB,
    169                                             MachineBasicBlock *TBB,
    170                                             MachineBasicBlock *FBB,
    171                                             ArrayRef<MachineOperand> Cond,
    172                                             const DebugLoc &DL,
    173                                             int *BytesAdded) const {
    174   assert(!BytesAdded && "code size not handled");
    175 
    176   if (Cond.empty()) {
    177     if (!TBB)
    178       return 0;
    179 
    180     BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
    181     return 1;
    182   }
    183 
    184   assert(Cond.size() == 2 && "Expected a flag and a successor block");
    185 
    186   if (Cond[0].getImm()) {
    187     BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]);
    188   } else {
    189     BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]);
    190   }
    191   if (!FBB)
    192     return 1;
    193 
    194   BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
    195   return 2;
    196 }
    197 
    198 bool WebAssemblyInstrInfo::reverseBranchCondition(
    199     SmallVectorImpl<MachineOperand> &Cond) const {
    200   assert(Cond.size() == 2 && "Expected a flag and a successor block");
    201   Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
    202   return false;
    203 }
    204