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 * 81 WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, 82 unsigned OpIdx1, 83 unsigned OpIdx2) const { 84 // If the operands are stackified, we can't reorder them. 85 WebAssemblyFunctionInfo &MFI = 86 *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>(); 87 if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) || 88 MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg())) 89 return nullptr; 90 91 // Otherwise use the default implementation. 92 return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2); 93 } 94 95 // Branch analysis. 96 bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 97 MachineBasicBlock *&TBB, 98 MachineBasicBlock *&FBB, 99 SmallVectorImpl<MachineOperand> &Cond, 100 bool /*AllowModify*/) const { 101 bool HaveCond = false; 102 for (MachineInstr &MI : MBB.terminators()) { 103 switch (MI.getOpcode()) { 104 default: 105 // Unhandled instruction; bail out. 106 return true; 107 case WebAssembly::BR_IF: 108 if (HaveCond) 109 return true; 110 // If we're running after CFGStackify, we can't optimize further. 111 if (!MI.getOperand(0).isMBB()) 112 return true; 113 Cond.push_back(MachineOperand::CreateImm(true)); 114 Cond.push_back(MI.getOperand(1)); 115 TBB = MI.getOperand(0).getMBB(); 116 HaveCond = true; 117 break; 118 case WebAssembly::BR_UNLESS: 119 if (HaveCond) 120 return true; 121 // If we're running after CFGStackify, we can't optimize further. 122 if (!MI.getOperand(0).isMBB()) 123 return true; 124 Cond.push_back(MachineOperand::CreateImm(false)); 125 Cond.push_back(MI.getOperand(1)); 126 TBB = MI.getOperand(0).getMBB(); 127 HaveCond = true; 128 break; 129 case WebAssembly::BR: 130 // If we're running after CFGStackify, we can't optimize further. 131 if (!MI.getOperand(0).isMBB()) 132 return true; 133 if (!HaveCond) 134 TBB = MI.getOperand(0).getMBB(); 135 else 136 FBB = MI.getOperand(0).getMBB(); 137 break; 138 } 139 if (MI.isBarrier()) 140 break; 141 } 142 143 return false; 144 } 145 146 unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB, 147 int *BytesRemoved) const { 148 assert(!BytesRemoved && "code size not handled"); 149 150 MachineBasicBlock::instr_iterator I = MBB.instr_end(); 151 unsigned Count = 0; 152 153 while (I != MBB.instr_begin()) { 154 --I; 155 if (I->isDebugInstr()) 156 continue; 157 if (!I->isTerminator()) 158 break; 159 // Remove the branch. 160 I->eraseFromParent(); 161 I = MBB.instr_end(); 162 ++Count; 163 } 164 165 return Count; 166 } 167 168 unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB, 169 MachineBasicBlock *TBB, 170 MachineBasicBlock *FBB, 171 ArrayRef<MachineOperand> Cond, 172 const DebugLoc &DL, 173 int *BytesAdded) const { 174 assert(!BytesAdded && "code size not handled"); 175 176 if (Cond.empty()) { 177 if (!TBB) 178 return 0; 179 180 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB); 181 return 1; 182 } 183 184 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 185 186 if (Cond[0].getImm()) { 187 BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]); 188 } else { 189 BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]); 190 } 191 if (!FBB) 192 return 1; 193 194 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB); 195 return 2; 196 } 197 198 bool WebAssemblyInstrInfo::reverseBranchCondition( 199 SmallVectorImpl<MachineOperand> &Cond) const { 200 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 201 Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm()); 202 return false; 203 } 204