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