WebAssemblyInstrInfo.cpp revision 309124
1285163Sdim//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
2285163Sdim//
3285163Sdim//                     The LLVM Compiler Infrastructure
4285163Sdim//
5285163Sdim// This file is distributed under the University of Illinois Open Source
6285163Sdim// License. See LICENSE.TXT for details.
7285163Sdim//
8285163Sdim//===----------------------------------------------------------------------===//
9285163Sdim///
10285163Sdim/// \file
11285163Sdim/// \brief This file contains the WebAssembly implementation of the
12285163Sdim/// TargetInstrInfo class.
13285163Sdim///
14285163Sdim//===----------------------------------------------------------------------===//
15285163Sdim
16285163Sdim#include "WebAssemblyInstrInfo.h"
17285163Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18309124Sdim#include "WebAssemblyMachineFunctionInfo.h"
19285163Sdim#include "WebAssemblySubtarget.h"
20285163Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
21285163Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
22285163Sdim#include "llvm/CodeGen/MachineMemOperand.h"
23285163Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
24285163Sdimusing namespace llvm;
25285163Sdim
26285163Sdim#define DEBUG_TYPE "wasm-instr-info"
27285163Sdim
28296417Sdim#define GET_INSTRINFO_CTOR_DTOR
29296417Sdim#include "WebAssemblyGenInstrInfo.inc"
30296417Sdim
31285163SdimWebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
32296417Sdim    : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
33296417Sdim                              WebAssembly::ADJCALLSTACKUP),
34296417Sdim      RI(STI.getTargetTriple()) {}
35296417Sdim
36309124Sdimbool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
37309124Sdim    const MachineInstr &MI, AliasAnalysis *AA) const {
38309124Sdim  switch (MI.getOpcode()) {
39309124Sdim  case WebAssembly::CONST_I32:
40309124Sdim  case WebAssembly::CONST_I64:
41309124Sdim  case WebAssembly::CONST_F32:
42309124Sdim  case WebAssembly::CONST_F64:
43309124Sdim    // isReallyTriviallyReMaterializableGeneric misses these because of the
44309124Sdim    // ARGUMENTS implicit def, so we manualy override it here.
45309124Sdim    return true;
46309124Sdim  default:
47309124Sdim    return false;
48309124Sdim  }
49309124Sdim}
50309124Sdim
51296417Sdimvoid WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
52296417Sdim                                       MachineBasicBlock::iterator I,
53309124Sdim                                       const DebugLoc &DL, unsigned DestReg,
54296417Sdim                                       unsigned SrcReg, bool KillSrc) const {
55296417Sdim  // This method is called by post-RA expansion, which expects only pregs to
56296417Sdim  // exist. However we need to handle both here.
57296417Sdim  auto &MRI = MBB.getParent()->getRegInfo();
58309124Sdim  const TargetRegisterClass *RC =
59309124Sdim      TargetRegisterInfo::isVirtualRegister(DestReg)
60309124Sdim          ? MRI.getRegClass(DestReg)
61309124Sdim          : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
62296417Sdim
63296417Sdim  unsigned CopyLocalOpcode;
64296417Sdim  if (RC == &WebAssembly::I32RegClass)
65296417Sdim    CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32;
66296417Sdim  else if (RC == &WebAssembly::I64RegClass)
67296417Sdim    CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64;
68296417Sdim  else if (RC == &WebAssembly::F32RegClass)
69296417Sdim    CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32;
70296417Sdim  else if (RC == &WebAssembly::F64RegClass)
71296417Sdim    CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64;
72296417Sdim  else
73296417Sdim    llvm_unreachable("Unexpected register class");
74296417Sdim
75296417Sdim  BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg)
76296417Sdim      .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
77296417Sdim}
78296417Sdim
79309124SdimMachineInstr *
80309124SdimWebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
81309124Sdim                                             unsigned OpIdx1,
82309124Sdim                                             unsigned OpIdx2) const {
83309124Sdim  // If the operands are stackified, we can't reorder them.
84309124Sdim  WebAssemblyFunctionInfo &MFI =
85309124Sdim      *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
86309124Sdim  if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
87309124Sdim      MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))
88309124Sdim    return nullptr;
89309124Sdim
90309124Sdim  // Otherwise use the default implementation.
91309124Sdim  return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
92309124Sdim}
93309124Sdim
94296417Sdim// Branch analysis.
95309124Sdimbool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
96296417Sdim                                         MachineBasicBlock *&TBB,
97296417Sdim                                         MachineBasicBlock *&FBB,
98296417Sdim                                         SmallVectorImpl<MachineOperand> &Cond,
99296417Sdim                                         bool /*AllowModify*/) const {
100296417Sdim  bool HaveCond = false;
101296417Sdim  for (MachineInstr &MI : MBB.terminators()) {
102296417Sdim    switch (MI.getOpcode()) {
103296417Sdim    default:
104296417Sdim      // Unhandled instruction; bail out.
105296417Sdim      return true;
106296417Sdim    case WebAssembly::BR_IF:
107296417Sdim      if (HaveCond)
108296417Sdim        return true;
109296417Sdim      // If we're running after CFGStackify, we can't optimize further.
110309124Sdim      if (!MI.getOperand(0).isMBB())
111296417Sdim        return true;
112296417Sdim      Cond.push_back(MachineOperand::CreateImm(true));
113309124Sdim      Cond.push_back(MI.getOperand(1));
114309124Sdim      TBB = MI.getOperand(0).getMBB();
115296417Sdim      HaveCond = true;
116296417Sdim      break;
117296417Sdim    case WebAssembly::BR_UNLESS:
118296417Sdim      if (HaveCond)
119296417Sdim        return true;
120296417Sdim      // If we're running after CFGStackify, we can't optimize further.
121309124Sdim      if (!MI.getOperand(0).isMBB())
122296417Sdim        return true;
123296417Sdim      Cond.push_back(MachineOperand::CreateImm(false));
124309124Sdim      Cond.push_back(MI.getOperand(1));
125309124Sdim      TBB = MI.getOperand(0).getMBB();
126296417Sdim      HaveCond = true;
127296417Sdim      break;
128296417Sdim    case WebAssembly::BR:
129296417Sdim      // If we're running after CFGStackify, we can't optimize further.
130296417Sdim      if (!MI.getOperand(0).isMBB())
131296417Sdim        return true;
132296417Sdim      if (!HaveCond)
133296417Sdim        TBB = MI.getOperand(0).getMBB();
134296417Sdim      else
135296417Sdim        FBB = MI.getOperand(0).getMBB();
136296417Sdim      break;
137296417Sdim    }
138296417Sdim    if (MI.isBarrier())
139296417Sdim      break;
140296417Sdim  }
141296417Sdim
142296417Sdim  return false;
143296417Sdim}
144296417Sdim
145296417Sdimunsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
146296417Sdim  MachineBasicBlock::instr_iterator I = MBB.instr_end();
147296417Sdim  unsigned Count = 0;
148296417Sdim
149296417Sdim  while (I != MBB.instr_begin()) {
150296417Sdim    --I;
151296417Sdim    if (I->isDebugValue())
152296417Sdim      continue;
153296417Sdim    if (!I->isTerminator())
154296417Sdim      break;
155296417Sdim    // Remove the branch.
156296417Sdim    I->eraseFromParent();
157296417Sdim    I = MBB.instr_end();
158296417Sdim    ++Count;
159296417Sdim  }
160296417Sdim
161296417Sdim  return Count;
162296417Sdim}
163296417Sdim
164296417Sdimunsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB,
165296417Sdim                                            MachineBasicBlock *TBB,
166296417Sdim                                            MachineBasicBlock *FBB,
167296417Sdim                                            ArrayRef<MachineOperand> Cond,
168309124Sdim                                            const DebugLoc &DL) const {
169296417Sdim  if (Cond.empty()) {
170296417Sdim    if (!TBB)
171296417Sdim      return 0;
172296417Sdim
173296417Sdim    BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
174296417Sdim    return 1;
175296417Sdim  }
176296417Sdim
177296417Sdim  assert(Cond.size() == 2 && "Expected a flag and a successor block");
178296417Sdim
179296417Sdim  if (Cond[0].getImm()) {
180309124Sdim    BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).addOperand(Cond[1]);
181296417Sdim  } else {
182296417Sdim    BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS))
183309124Sdim        .addMBB(TBB)
184309124Sdim        .addOperand(Cond[1]);
185296417Sdim  }
186296417Sdim  if (!FBB)
187296417Sdim    return 1;
188296417Sdim
189296417Sdim  BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
190296417Sdim  return 2;
191296417Sdim}
192296417Sdim
193296417Sdimbool WebAssemblyInstrInfo::ReverseBranchCondition(
194296417Sdim    SmallVectorImpl<MachineOperand> &Cond) const {
195296417Sdim  assert(Cond.size() == 2 && "Expected a flag and a successor block");
196296417Sdim  Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
197296417Sdim  return false;
198296417Sdim}
199