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