110e730a2SDan Gohman //===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
210e730a2SDan Gohman //
310e730a2SDan Gohman //                     The LLVM Compiler Infrastructure
410e730a2SDan Gohman //
510e730a2SDan Gohman // This file is distributed under the University of Illinois Open Source
610e730a2SDan Gohman // License. See LICENSE.TXT for details.
710e730a2SDan Gohman //
810e730a2SDan Gohman //===----------------------------------------------------------------------===//
910e730a2SDan Gohman ///
1010e730a2SDan Gohman /// \file
1110e730a2SDan Gohman /// \brief This file contains the WebAssembly implementation of the
1210e730a2SDan Gohman /// TargetInstrInfo class.
1310e730a2SDan Gohman ///
1410e730a2SDan Gohman //===----------------------------------------------------------------------===//
1510e730a2SDan Gohman 
1610e730a2SDan Gohman #include "WebAssemblyInstrInfo.h"
1710e730a2SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18adf28177SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
1910e730a2SDan Gohman #include "WebAssemblySubtarget.h"
2010e730a2SDan Gohman #include "llvm/CodeGen/MachineFrameInfo.h"
2110e730a2SDan Gohman #include "llvm/CodeGen/MachineInstrBuilder.h"
2210e730a2SDan Gohman #include "llvm/CodeGen/MachineMemOperand.h"
2310e730a2SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
2410e730a2SDan Gohman using namespace llvm;
2510e730a2SDan Gohman 
2610e730a2SDan Gohman #define DEBUG_TYPE "wasm-instr-info"
2710e730a2SDan Gohman 
28b9073fb2SJF Bastien #define GET_INSTRINFO_CTOR_DTOR
29b9073fb2SJF Bastien #include "WebAssemblyGenInstrInfo.inc"
30b9073fb2SJF Bastien 
3110e730a2SDan Gohman WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
3235bfb24cSDan Gohman     : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
3335bfb24cSDan Gohman                               WebAssembly::ADJCALLSTACKUP),
3435bfb24cSDan Gohman       RI(STI.getTargetTriple()) {}
354f52e00eSDan Gohman 
36b6fd39a3SDan Gohman bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
37b6fd39a3SDan Gohman     const MachineInstr *MI, AliasAnalysis *AA) const {
38b6fd39a3SDan Gohman   switch (MI->getOpcode()) {
39b6fd39a3SDan Gohman   case WebAssembly::CONST_I32:
40b6fd39a3SDan Gohman   case WebAssembly::CONST_I64:
41b6fd39a3SDan Gohman   case WebAssembly::CONST_F32:
42b6fd39a3SDan Gohman   case WebAssembly::CONST_F64:
43b6fd39a3SDan Gohman     // isReallyTriviallyReMaterializableGeneric misses these because of the
44b6fd39a3SDan Gohman     // ARGUMENTS implicit def, so we manualy override it here.
45b6fd39a3SDan Gohman     return true;
46b6fd39a3SDan Gohman   default:
47b6fd39a3SDan Gohman     return false;
48b6fd39a3SDan Gohman   }
49b6fd39a3SDan Gohman }
50b6fd39a3SDan Gohman 
514f52e00eSDan Gohman void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
524f52e00eSDan Gohman                                        MachineBasicBlock::iterator I,
53*bdc4956bSBenjamin Kramer                                        const DebugLoc &DL, unsigned DestReg,
544f52e00eSDan Gohman                                        unsigned SrcReg, bool KillSrc) const {
558bb5f292SDerek Schuff   // This method is called by post-RA expansion, which expects only pregs to
568bb5f292SDerek Schuff   // exist. However we need to handle both here.
578bb5f292SDerek Schuff   auto &MRI = MBB.getParent()->getRegInfo();
58b6fd39a3SDan Gohman   const TargetRegisterClass *RC =
59b6fd39a3SDan Gohman       TargetRegisterInfo::isVirtualRegister(DestReg)
60b6fd39a3SDan Gohman           ? MRI.getRegClass(DestReg)
616ea637afSDerek Schuff           : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
624ba4816bSDan Gohman 
63aa0a4bd0SDan Gohman   unsigned CopyLocalOpcode;
644ba4816bSDan Gohman   if (RC == &WebAssembly::I32RegClass)
65aa0a4bd0SDan Gohman     CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32;
664ba4816bSDan Gohman   else if (RC == &WebAssembly::I64RegClass)
67aa0a4bd0SDan Gohman     CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64;
684ba4816bSDan Gohman   else if (RC == &WebAssembly::F32RegClass)
69aa0a4bd0SDan Gohman     CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32;
704ba4816bSDan Gohman   else if (RC == &WebAssembly::F64RegClass)
71aa0a4bd0SDan Gohman     CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64;
724ba4816bSDan Gohman   else
734ba4816bSDan Gohman     llvm_unreachable("Unexpected register class");
744ba4816bSDan Gohman 
75aa0a4bd0SDan Gohman   BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg)
764f52e00eSDan Gohman       .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
774f52e00eSDan Gohman }
78950a13cfSDan Gohman 
79adf28177SDan Gohman MachineInstr *
80adf28177SDan Gohman WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr *MI, bool NewMI,
81adf28177SDan Gohman                                              unsigned OpIdx1,
82adf28177SDan Gohman                                              unsigned OpIdx2) const {
83adf28177SDan Gohman   // If the operands are stackified, we can't reorder them.
84adf28177SDan Gohman   WebAssemblyFunctionInfo &MFI =
85adf28177SDan Gohman       *MI->getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
86adf28177SDan Gohman   if (MFI.isVRegStackified(MI->getOperand(OpIdx1).getReg()) ||
87adf28177SDan Gohman       MFI.isVRegStackified(MI->getOperand(OpIdx2).getReg()))
88adf28177SDan Gohman     return nullptr;
89adf28177SDan Gohman 
90adf28177SDan Gohman   // Otherwise use the default implementation.
91adf28177SDan Gohman   return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
92adf28177SDan Gohman }
93adf28177SDan Gohman 
94950a13cfSDan Gohman // Branch analysis.
95950a13cfSDan Gohman bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
96950a13cfSDan Gohman                                          MachineBasicBlock *&TBB,
97950a13cfSDan Gohman                                          MachineBasicBlock *&FBB,
98950a13cfSDan Gohman                                          SmallVectorImpl<MachineOperand> &Cond,
997a6b9825SDan Gohman                                          bool /*AllowModify*/) const {
100950a13cfSDan Gohman   bool HaveCond = false;
101d544e0c1SDan Gohman   for (MachineInstr &MI : MBB.terminators()) {
102950a13cfSDan Gohman     switch (MI.getOpcode()) {
103950a13cfSDan Gohman     default:
104950a13cfSDan Gohman       // Unhandled instruction; bail out.
105950a13cfSDan Gohman       return true;
106231244c3SDan Gohman     case WebAssembly::BR_IF:
107950a13cfSDan Gohman       if (HaveCond)
108950a13cfSDan Gohman         return true;
1091d68e80fSDan Gohman       // If we're running after CFGStackify, we can't optimize further.
11006b49582SDan Gohman       if (!MI.getOperand(0).isMBB())
1111d68e80fSDan Gohman         return true;
112f0b165a7SDan Gohman       Cond.push_back(MachineOperand::CreateImm(true));
11306b49582SDan Gohman       Cond.push_back(MI.getOperand(1));
11406b49582SDan Gohman       TBB = MI.getOperand(0).getMBB();
115f0b165a7SDan Gohman       HaveCond = true;
116f0b165a7SDan Gohman       break;
117f0b165a7SDan Gohman     case WebAssembly::BR_UNLESS:
118f0b165a7SDan Gohman       if (HaveCond)
119f0b165a7SDan Gohman         return true;
1201d68e80fSDan Gohman       // If we're running after CFGStackify, we can't optimize further.
12106b49582SDan Gohman       if (!MI.getOperand(0).isMBB())
1221d68e80fSDan Gohman         return true;
123f0b165a7SDan Gohman       Cond.push_back(MachineOperand::CreateImm(false));
12406b49582SDan Gohman       Cond.push_back(MI.getOperand(1));
12506b49582SDan Gohman       TBB = MI.getOperand(0).getMBB();
126950a13cfSDan Gohman       HaveCond = true;
127950a13cfSDan Gohman       break;
128950a13cfSDan Gohman     case WebAssembly::BR:
1291d68e80fSDan Gohman       // If we're running after CFGStackify, we can't optimize further.
1301d68e80fSDan Gohman       if (!MI.getOperand(0).isMBB())
1311d68e80fSDan Gohman         return true;
132950a13cfSDan Gohman       if (!HaveCond)
133950a13cfSDan Gohman         TBB = MI.getOperand(0).getMBB();
134950a13cfSDan Gohman       else
135950a13cfSDan Gohman         FBB = MI.getOperand(0).getMBB();
136950a13cfSDan Gohman       break;
137950a13cfSDan Gohman     }
138950a13cfSDan Gohman     if (MI.isBarrier())
139950a13cfSDan Gohman       break;
140950a13cfSDan Gohman   }
141950a13cfSDan Gohman 
142950a13cfSDan Gohman   return false;
143950a13cfSDan Gohman }
144950a13cfSDan Gohman 
145950a13cfSDan Gohman unsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
146950a13cfSDan Gohman   MachineBasicBlock::instr_iterator I = MBB.instr_end();
147950a13cfSDan Gohman   unsigned Count = 0;
148950a13cfSDan Gohman 
149950a13cfSDan Gohman   while (I != MBB.instr_begin()) {
150950a13cfSDan Gohman     --I;
151950a13cfSDan Gohman     if (I->isDebugValue())
152950a13cfSDan Gohman       continue;
153950a13cfSDan Gohman     if (!I->isTerminator())
154950a13cfSDan Gohman       break;
155950a13cfSDan Gohman     // Remove the branch.
156950a13cfSDan Gohman     I->eraseFromParent();
157950a13cfSDan Gohman     I = MBB.instr_end();
158950a13cfSDan Gohman     ++Count;
159950a13cfSDan Gohman   }
160950a13cfSDan Gohman 
161950a13cfSDan Gohman   return Count;
162950a13cfSDan Gohman }
163950a13cfSDan Gohman 
1647a6b9825SDan Gohman unsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB,
1657a6b9825SDan Gohman                                             MachineBasicBlock *TBB,
1667a6b9825SDan Gohman                                             MachineBasicBlock *FBB,
1677a6b9825SDan Gohman                                             ArrayRef<MachineOperand> Cond,
168*bdc4956bSBenjamin Kramer                                             const DebugLoc &DL) const {
169950a13cfSDan Gohman   if (Cond.empty()) {
170950a13cfSDan Gohman     if (!TBB)
171950a13cfSDan Gohman       return 0;
172950a13cfSDan Gohman 
173950a13cfSDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
174950a13cfSDan Gohman     return 1;
175950a13cfSDan Gohman   }
176950a13cfSDan Gohman 
177f0b165a7SDan Gohman   assert(Cond.size() == 2 && "Expected a flag and a successor block");
178f0b165a7SDan Gohman 
179f0b165a7SDan Gohman   if (Cond[0].getImm()) {
18006b49582SDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).addOperand(Cond[1]);
181f0b165a7SDan Gohman   } else {
182f0b165a7SDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS))
18306b49582SDan Gohman         .addMBB(TBB)
18406b49582SDan Gohman         .addOperand(Cond[1]);
185f0b165a7SDan Gohman   }
186950a13cfSDan Gohman   if (!FBB)
187950a13cfSDan Gohman     return 1;
188950a13cfSDan Gohman 
189950a13cfSDan Gohman   BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
190950a13cfSDan Gohman   return 2;
191950a13cfSDan Gohman }
192950a13cfSDan Gohman 
193950a13cfSDan Gohman bool WebAssemblyInstrInfo::ReverseBranchCondition(
194950a13cfSDan Gohman     SmallVectorImpl<MachineOperand> &Cond) const {
195f0b165a7SDan Gohman   assert(Cond.size() == 2 && "Expected a flag and a successor block");
196f0b165a7SDan Gohman   Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
197f0b165a7SDan Gohman   return false;
198950a13cfSDan Gohman }
199