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