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 bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable( 36 const MachineInstr *MI, AliasAnalysis *AA) const { 37 switch (MI->getOpcode()) { 38 case WebAssembly::CONST_I32: 39 case WebAssembly::CONST_I64: 40 case WebAssembly::CONST_F32: 41 case WebAssembly::CONST_F64: 42 // isReallyTriviallyReMaterializableGeneric misses these because of the 43 // ARGUMENTS implicit def, so we manualy override it here. 44 return true; 45 default: 46 return false; 47 } 48 } 49 50 void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 51 MachineBasicBlock::iterator I, 52 DebugLoc DL, unsigned DestReg, 53 unsigned SrcReg, bool KillSrc) const { 54 // This method is called by post-RA expansion, which expects only pregs to 55 // exist. However we need to handle both here. 56 auto &MRI = MBB.getParent()->getRegInfo(); 57 const TargetRegisterClass *RC = 58 TargetRegisterInfo::isVirtualRegister(DestReg) 59 ? MRI.getRegClass(DestReg) 60 : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(SrcReg); 61 62 unsigned CopyLocalOpcode; 63 if (RC == &WebAssembly::I32RegClass) 64 CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32; 65 else if (RC == &WebAssembly::I64RegClass) 66 CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64; 67 else if (RC == &WebAssembly::F32RegClass) 68 CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32; 69 else if (RC == &WebAssembly::F64RegClass) 70 CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64; 71 else 72 llvm_unreachable("Unexpected register class"); 73 74 BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg) 75 .addReg(SrcReg, KillSrc ? RegState::Kill : 0); 76 } 77 78 // Branch analysis. 79 bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 80 MachineBasicBlock *&TBB, 81 MachineBasicBlock *&FBB, 82 SmallVectorImpl<MachineOperand> &Cond, 83 bool /*AllowModify*/) const { 84 bool HaveCond = false; 85 for (MachineInstr &MI : MBB.terminators()) { 86 switch (MI.getOpcode()) { 87 default: 88 // Unhandled instruction; bail out. 89 return true; 90 case WebAssembly::BR_IF: 91 if (HaveCond) 92 return true; 93 // If we're running after CFGStackify, we can't optimize further. 94 if (!MI.getOperand(1).isMBB()) 95 return true; 96 Cond.push_back(MachineOperand::CreateImm(true)); 97 Cond.push_back(MI.getOperand(0)); 98 TBB = MI.getOperand(1).getMBB(); 99 HaveCond = true; 100 break; 101 case WebAssembly::BR_UNLESS: 102 if (HaveCond) 103 return true; 104 // If we're running after CFGStackify, we can't optimize further. 105 if (!MI.getOperand(1).isMBB()) 106 return true; 107 Cond.push_back(MachineOperand::CreateImm(false)); 108 Cond.push_back(MI.getOperand(0)); 109 TBB = MI.getOperand(1).getMBB(); 110 HaveCond = true; 111 break; 112 case WebAssembly::BR: 113 // If we're running after CFGStackify, we can't optimize further. 114 if (!MI.getOperand(0).isMBB()) 115 return true; 116 if (!HaveCond) 117 TBB = MI.getOperand(0).getMBB(); 118 else 119 FBB = MI.getOperand(0).getMBB(); 120 break; 121 } 122 if (MI.isBarrier()) 123 break; 124 } 125 126 return false; 127 } 128 129 unsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 130 MachineBasicBlock::instr_iterator I = MBB.instr_end(); 131 unsigned Count = 0; 132 133 while (I != MBB.instr_begin()) { 134 --I; 135 if (I->isDebugValue()) 136 continue; 137 if (!I->isTerminator()) 138 break; 139 // Remove the branch. 140 I->eraseFromParent(); 141 I = MBB.instr_end(); 142 ++Count; 143 } 144 145 return Count; 146 } 147 148 unsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB, 149 MachineBasicBlock *TBB, 150 MachineBasicBlock *FBB, 151 ArrayRef<MachineOperand> Cond, 152 DebugLoc DL) const { 153 if (Cond.empty()) { 154 if (!TBB) 155 return 0; 156 157 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB); 158 return 1; 159 } 160 161 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 162 163 if (Cond[0].getImm()) { 164 BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addOperand(Cond[1]).addMBB(TBB); 165 } else { 166 BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)) 167 .addOperand(Cond[1]) 168 .addMBB(TBB); 169 } 170 if (!FBB) 171 return 1; 172 173 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB); 174 return 2; 175 } 176 177 bool WebAssemblyInstrInfo::ReverseBranchCondition( 178 SmallVectorImpl<MachineOperand> &Cond) const { 179 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 180 Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm()); 181 return false; 182 } 183