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 Cond.push_back(MachineOperand::CreateImm(true)); 78 Cond.push_back(MI.getOperand(0)); 79 TBB = MI.getOperand(1).getMBB(); 80 HaveCond = true; 81 break; 82 case WebAssembly::BR_UNLESS: 83 if (HaveCond) 84 return true; 85 Cond.push_back(MachineOperand::CreateImm(false)); 86 Cond.push_back(MI.getOperand(0)); 87 TBB = MI.getOperand(1).getMBB(); 88 HaveCond = true; 89 break; 90 case WebAssembly::BR: 91 if (!HaveCond) 92 TBB = MI.getOperand(0).getMBB(); 93 else 94 FBB = MI.getOperand(0).getMBB(); 95 break; 96 } 97 if (MI.isBarrier()) 98 break; 99 } 100 101 return false; 102 } 103 104 unsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 105 MachineBasicBlock::instr_iterator I = MBB.instr_end(); 106 unsigned Count = 0; 107 108 while (I != MBB.instr_begin()) { 109 --I; 110 if (I->isDebugValue()) 111 continue; 112 if (!I->isTerminator()) 113 break; 114 // Remove the branch. 115 I->eraseFromParent(); 116 I = MBB.instr_end(); 117 ++Count; 118 } 119 120 return Count; 121 } 122 123 unsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB, 124 MachineBasicBlock *TBB, 125 MachineBasicBlock *FBB, 126 ArrayRef<MachineOperand> Cond, 127 DebugLoc DL) const { 128 if (Cond.empty()) { 129 if (!TBB) 130 return 0; 131 132 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB); 133 return 1; 134 } 135 136 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 137 138 if (Cond[0].getImm()) { 139 BuildMI(&MBB, DL, get(WebAssembly::BR_IF)) 140 .addOperand(Cond[1]) 141 .addMBB(TBB); 142 } else { 143 BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)) 144 .addOperand(Cond[1]) 145 .addMBB(TBB); 146 } 147 if (!FBB) 148 return 1; 149 150 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB); 151 return 2; 152 } 153 154 bool WebAssemblyInstrInfo::ReverseBranchCondition( 155 SmallVectorImpl<MachineOperand> &Cond) const { 156 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 157 Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm()); 158 return false; 159 } 160