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