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(
379cfc75c2SDuncan P. N. Exon Smith     const MachineInstr &MI, AliasAnalysis *AA) const {
389cfc75c2SDuncan P. N. Exon Smith   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,
53bdc4956bSBenjamin 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 
63*4fc4e42dSDan Gohman   unsigned CopyOpcode;
644ba4816bSDan Gohman   if (RC == &WebAssembly::I32RegClass)
65*4fc4e42dSDan Gohman     CopyOpcode = WebAssembly::COPY_I32;
664ba4816bSDan Gohman   else if (RC == &WebAssembly::I64RegClass)
67*4fc4e42dSDan Gohman     CopyOpcode = WebAssembly::COPY_I64;
684ba4816bSDan Gohman   else if (RC == &WebAssembly::F32RegClass)
69*4fc4e42dSDan Gohman     CopyOpcode = WebAssembly::COPY_F32;
704ba4816bSDan Gohman   else if (RC == &WebAssembly::F64RegClass)
71*4fc4e42dSDan Gohman     CopyOpcode = WebAssembly::COPY_F64;
724ba4816bSDan Gohman   else
734ba4816bSDan Gohman     llvm_unreachable("Unexpected register class");
744ba4816bSDan Gohman 
75*4fc4e42dSDan Gohman   BuildMI(MBB, I, DL, get(CopyOpcode), DestReg)
764f52e00eSDan Gohman       .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
774f52e00eSDan Gohman }
78950a13cfSDan Gohman 
79adf28177SDan Gohman MachineInstr *
809cfc75c2SDuncan P. N. Exon Smith 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 =
859cfc75c2SDuncan P. N. Exon Smith       *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
869cfc75c2SDuncan P. N. Exon Smith   if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
879cfc75c2SDuncan P. N. Exon Smith       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.
9571c30a14SJacques Pienaar 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 
1451b9fc8edSMatt Arsenault unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
146a2b036e8SMatt Arsenault                                             int *BytesRemoved) const {
147a2b036e8SMatt Arsenault   assert(!BytesRemoved && "code size not handled");
148a2b036e8SMatt Arsenault 
149950a13cfSDan Gohman   MachineBasicBlock::instr_iterator I = MBB.instr_end();
150950a13cfSDan Gohman   unsigned Count = 0;
151950a13cfSDan Gohman 
152950a13cfSDan Gohman   while (I != MBB.instr_begin()) {
153950a13cfSDan Gohman     --I;
154950a13cfSDan Gohman     if (I->isDebugValue())
155950a13cfSDan Gohman       continue;
156950a13cfSDan Gohman     if (!I->isTerminator())
157950a13cfSDan Gohman       break;
158950a13cfSDan Gohman     // Remove the branch.
159950a13cfSDan Gohman     I->eraseFromParent();
160950a13cfSDan Gohman     I = MBB.instr_end();
161950a13cfSDan Gohman     ++Count;
162950a13cfSDan Gohman   }
163950a13cfSDan Gohman 
164950a13cfSDan Gohman   return Count;
165950a13cfSDan Gohman }
166950a13cfSDan Gohman 
167e8e0f5caSMatt Arsenault unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB,
1687a6b9825SDan Gohman                                             MachineBasicBlock *TBB,
1697a6b9825SDan Gohman                                             MachineBasicBlock *FBB,
1707a6b9825SDan Gohman                                             ArrayRef<MachineOperand> Cond,
171a2b036e8SMatt Arsenault                                             const DebugLoc &DL,
172a2b036e8SMatt Arsenault                                             int *BytesAdded) const {
173a2b036e8SMatt Arsenault   assert(!BytesAdded && "code size not handled");
174a2b036e8SMatt Arsenault 
175950a13cfSDan Gohman   if (Cond.empty()) {
176950a13cfSDan Gohman     if (!TBB)
177950a13cfSDan Gohman       return 0;
178950a13cfSDan Gohman 
179950a13cfSDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
180950a13cfSDan Gohman     return 1;
181950a13cfSDan Gohman   }
182950a13cfSDan Gohman 
183f0b165a7SDan Gohman   assert(Cond.size() == 2 && "Expected a flag and a successor block");
184f0b165a7SDan Gohman 
185f0b165a7SDan Gohman   if (Cond[0].getImm()) {
18606b49582SDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).addOperand(Cond[1]);
187f0b165a7SDan Gohman   } else {
188f0b165a7SDan Gohman     BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS))
18906b49582SDan Gohman         .addMBB(TBB)
19006b49582SDan Gohman         .addOperand(Cond[1]);
191f0b165a7SDan Gohman   }
192950a13cfSDan Gohman   if (!FBB)
193950a13cfSDan Gohman     return 1;
194950a13cfSDan Gohman 
195950a13cfSDan Gohman   BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
196950a13cfSDan Gohman   return 2;
197950a13cfSDan Gohman }
198950a13cfSDan Gohman 
1991b9fc8edSMatt Arsenault bool WebAssemblyInstrInfo::reverseBranchCondition(
200950a13cfSDan Gohman     SmallVectorImpl<MachineOperand> &Cond) const {
201f0b165a7SDan Gohman   assert(Cond.size() == 2 && "Expected a flag and a successor block");
202f0b165a7SDan Gohman   Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
203f0b165a7SDan Gohman   return false;
204950a13cfSDan Gohman }
205