1cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
2cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
3cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
4cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
5cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
6cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// License. See LICENSE.TXT for details.
7cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
8cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
9cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
10cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// \file
11cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// \brief This file contains the WebAssembly implementation of the
12cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// TargetInstrInfo class.
13cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
14cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
15cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
16cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "WebAssemblyInstrInfo.h"
17cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "WebAssemblySubtarget.h"
19cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/CodeGen/MachineFrameInfo.h"
20cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/CodeGen/MachineInstrBuilder.h"
21cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/CodeGen/MachineMemOperand.h"
22cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/CodeGen/MachineRegisterInfo.h"
23cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarusing namespace llvm;
24cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
25cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#define DEBUG_TYPE "wasm-instr-info"
26cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
27cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#define GET_INSTRINFO_CTOR_DTOR
28cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "WebAssemblyGenInstrInfo.inc"
29cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
30cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarWebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
31cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
32cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                              WebAssembly::ADJCALLSTACKUP),
33cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      RI(STI.getTargetTriple()) {}
34cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
35cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarvoid WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
36cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                       MachineBasicBlock::iterator I,
37cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                       DebugLoc DL, unsigned DestReg,
38cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                       unsigned SrcReg, bool KillSrc) const {
39cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // This method is called by post-RA expansion, which expects only pregs to
40cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // exist. However we need to handle both here.
41cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  auto &MRI = MBB.getParent()->getRegInfo();
42cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  const TargetRegisterClass *RC = TargetRegisterInfo::isVirtualRegister(DestReg) ?
43cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      MRI.getRegClass(DestReg) :
44cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(SrcReg);
45cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
46cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  unsigned CopyLocalOpcode;
47cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (RC == &WebAssembly::I32RegClass)
48cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32;
49cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  else if (RC == &WebAssembly::I64RegClass)
50cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64;
51cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  else if (RC == &WebAssembly::F32RegClass)
52cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32;
53cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  else if (RC == &WebAssembly::F64RegClass)
54cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64;
55cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  else
56cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    llvm_unreachable("Unexpected register class");
57cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
58cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg)
59cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
60cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
61cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
62cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Branch analysis.
63cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarbool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
64cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                         MachineBasicBlock *&TBB,
65cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                         MachineBasicBlock *&FBB,
66cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                         SmallVectorImpl<MachineOperand> &Cond,
67cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                         bool /*AllowModify*/) const {
68cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  bool HaveCond = false;
69cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (MachineInstr &MI : MBB.terminators()) {
70cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    switch (MI.getOpcode()) {
71cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    default:
72cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Unhandled instruction; bail out.
73cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return true;
74cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    case WebAssembly::BR_IF:
75cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (HaveCond)
76cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        return true;
77cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Cond.push_back(MachineOperand::CreateImm(true));
78cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Cond.push_back(MI.getOperand(0));
79cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      TBB = MI.getOperand(1).getMBB();
80cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      HaveCond = true;
81cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      break;
82cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    case WebAssembly::BR_UNLESS:
83cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (HaveCond)
84cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        return true;
85cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Cond.push_back(MachineOperand::CreateImm(false));
86cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Cond.push_back(MI.getOperand(0));
87cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      TBB = MI.getOperand(1).getMBB();
88cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      HaveCond = true;
89cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      break;
90cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    case WebAssembly::BR:
91cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (!HaveCond)
92cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        TBB = MI.getOperand(0).getMBB();
93cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      else
94cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FBB = MI.getOperand(0).getMBB();
95cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      break;
96cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
97cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (MI.isBarrier())
98cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      break;
99cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
100cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
101cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return false;
102cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
103cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
104cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarunsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
105cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  MachineBasicBlock::instr_iterator I = MBB.instr_end();
106cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  unsigned Count = 0;
107cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
108cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  while (I != MBB.instr_begin()) {
109cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    --I;
110cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (I->isDebugValue())
111cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      continue;
112cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!I->isTerminator())
113cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      break;
114cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Remove the branch.
115cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    I->eraseFromParent();
116cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    I = MBB.instr_end();
117cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    ++Count;
118cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
119cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
120cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return Count;
121cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
122cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
123cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarunsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB,
124cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                            MachineBasicBlock *TBB,
125cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                            MachineBasicBlock *FBB,
126cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                            ArrayRef<MachineOperand> Cond,
127cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                            DebugLoc DL) const {
128cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (Cond.empty()) {
129cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!TBB)
130cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return 0;
131cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
132cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
133cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return 1;
134cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
135cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
136cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  assert(Cond.size() == 2 && "Expected a flag and a successor block");
137cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
138cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (Cond[0].getImm()) {
139cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    BuildMI(&MBB, DL, get(WebAssembly::BR_IF))
140cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        .addOperand(Cond[1])
141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        .addMBB(TBB);
142cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  } else {
143cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS))
144cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        .addOperand(Cond[1])
145cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        .addMBB(TBB);
146cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
147cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!FBB)
148cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return 1;
149cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
150cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
151cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return 2;
152cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
153cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
154cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarbool WebAssemblyInstrInfo::ReverseBranchCondition(
155cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    SmallVectorImpl<MachineOperand> &Cond) const {
156cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  assert(Cond.size() == 2 && "Expected a flag and a successor block");
157cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
158cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return false;
159cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
160