WebAssemblyInstrInfo.cpp revision 344779
1285163Sdim//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===// 2285163Sdim// 3285163Sdim// The LLVM Compiler Infrastructure 4285163Sdim// 5285163Sdim// This file is distributed under the University of Illinois Open Source 6285163Sdim// License. See LICENSE.TXT for details. 7285163Sdim// 8285163Sdim//===----------------------------------------------------------------------===// 9285163Sdim/// 10285163Sdim/// \file 11341825Sdim/// This file contains the WebAssembly implementation of the 12285163Sdim/// TargetInstrInfo class. 13285163Sdim/// 14285163Sdim//===----------------------------------------------------------------------===// 15285163Sdim 16285163Sdim#include "WebAssemblyInstrInfo.h" 17285163Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 18309124Sdim#include "WebAssemblyMachineFunctionInfo.h" 19285163Sdim#include "WebAssemblySubtarget.h" 20285163Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 21285163Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 22285163Sdim#include "llvm/CodeGen/MachineMemOperand.h" 23285163Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 24285163Sdimusing namespace llvm; 25285163Sdim 26285163Sdim#define DEBUG_TYPE "wasm-instr-info" 27285163Sdim 28296417Sdim#define GET_INSTRINFO_CTOR_DTOR 29296417Sdim#include "WebAssemblyGenInstrInfo.inc" 30296417Sdim 31285163SdimWebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI) 32296417Sdim : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN, 33341825Sdim WebAssembly::ADJCALLSTACKUP, 34341825Sdim WebAssembly::CATCHRET), 35296417Sdim RI(STI.getTargetTriple()) {} 36296417Sdim 37309124Sdimbool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable( 38309124Sdim const MachineInstr &MI, AliasAnalysis *AA) const { 39309124Sdim switch (MI.getOpcode()) { 40309124Sdim case WebAssembly::CONST_I32: 41309124Sdim case WebAssembly::CONST_I64: 42309124Sdim case WebAssembly::CONST_F32: 43309124Sdim case WebAssembly::CONST_F64: 44309124Sdim // isReallyTriviallyReMaterializableGeneric misses these because of the 45309124Sdim // ARGUMENTS implicit def, so we manualy override it here. 46309124Sdim return true; 47309124Sdim default: 48309124Sdim return false; 49309124Sdim } 50309124Sdim} 51309124Sdim 52296417Sdimvoid WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 53296417Sdim MachineBasicBlock::iterator I, 54309124Sdim const DebugLoc &DL, unsigned DestReg, 55296417Sdim unsigned SrcReg, bool KillSrc) const { 56296417Sdim // This method is called by post-RA expansion, which expects only pregs to 57296417Sdim // exist. However we need to handle both here. 58296417Sdim auto &MRI = MBB.getParent()->getRegInfo(); 59309124Sdim const TargetRegisterClass *RC = 60309124Sdim TargetRegisterInfo::isVirtualRegister(DestReg) 61309124Sdim ? MRI.getRegClass(DestReg) 62309124Sdim : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg); 63296417Sdim 64314564Sdim unsigned CopyOpcode; 65296417Sdim if (RC == &WebAssembly::I32RegClass) 66314564Sdim CopyOpcode = WebAssembly::COPY_I32; 67296417Sdim else if (RC == &WebAssembly::I64RegClass) 68314564Sdim CopyOpcode = WebAssembly::COPY_I64; 69296417Sdim else if (RC == &WebAssembly::F32RegClass) 70314564Sdim CopyOpcode = WebAssembly::COPY_F32; 71296417Sdim else if (RC == &WebAssembly::F64RegClass) 72314564Sdim CopyOpcode = WebAssembly::COPY_F64; 73344779Sdim else if (RC == &WebAssembly::V128RegClass) 74344779Sdim CopyOpcode = WebAssembly::COPY_V128; 75296417Sdim else 76296417Sdim llvm_unreachable("Unexpected register class"); 77296417Sdim 78314564Sdim BuildMI(MBB, I, DL, get(CopyOpcode), DestReg) 79296417Sdim .addReg(SrcReg, KillSrc ? RegState::Kill : 0); 80296417Sdim} 81296417Sdim 82344779SdimMachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl( 83344779Sdim MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const { 84309124Sdim // If the operands are stackified, we can't reorder them. 85309124Sdim WebAssemblyFunctionInfo &MFI = 86309124Sdim *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>(); 87309124Sdim if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) || 88309124Sdim MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg())) 89309124Sdim return nullptr; 90309124Sdim 91309124Sdim // Otherwise use the default implementation. 92309124Sdim return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2); 93309124Sdim} 94309124Sdim 95296417Sdim// Branch analysis. 96309124Sdimbool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 97296417Sdim MachineBasicBlock *&TBB, 98296417Sdim MachineBasicBlock *&FBB, 99296417Sdim SmallVectorImpl<MachineOperand> &Cond, 100296417Sdim bool /*AllowModify*/) const { 101296417Sdim bool HaveCond = false; 102296417Sdim for (MachineInstr &MI : MBB.terminators()) { 103296417Sdim switch (MI.getOpcode()) { 104296417Sdim default: 105296417Sdim // Unhandled instruction; bail out. 106296417Sdim return true; 107296417Sdim case WebAssembly::BR_IF: 108296417Sdim if (HaveCond) 109296417Sdim return true; 110296417Sdim // If we're running after CFGStackify, we can't optimize further. 111309124Sdim if (!MI.getOperand(0).isMBB()) 112296417Sdim return true; 113296417Sdim Cond.push_back(MachineOperand::CreateImm(true)); 114309124Sdim Cond.push_back(MI.getOperand(1)); 115309124Sdim TBB = MI.getOperand(0).getMBB(); 116296417Sdim HaveCond = true; 117296417Sdim break; 118296417Sdim case WebAssembly::BR_UNLESS: 119296417Sdim if (HaveCond) 120296417Sdim return true; 121296417Sdim // If we're running after CFGStackify, we can't optimize further. 122309124Sdim if (!MI.getOperand(0).isMBB()) 123296417Sdim return true; 124296417Sdim Cond.push_back(MachineOperand::CreateImm(false)); 125309124Sdim Cond.push_back(MI.getOperand(1)); 126309124Sdim TBB = MI.getOperand(0).getMBB(); 127296417Sdim HaveCond = true; 128296417Sdim break; 129296417Sdim case WebAssembly::BR: 130296417Sdim // If we're running after CFGStackify, we can't optimize further. 131296417Sdim if (!MI.getOperand(0).isMBB()) 132296417Sdim return true; 133296417Sdim if (!HaveCond) 134296417Sdim TBB = MI.getOperand(0).getMBB(); 135296417Sdim else 136296417Sdim FBB = MI.getOperand(0).getMBB(); 137296417Sdim break; 138296417Sdim } 139296417Sdim if (MI.isBarrier()) 140296417Sdim break; 141296417Sdim } 142296417Sdim 143296417Sdim return false; 144296417Sdim} 145296417Sdim 146314564Sdimunsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB, 147314564Sdim int *BytesRemoved) const { 148314564Sdim assert(!BytesRemoved && "code size not handled"); 149314564Sdim 150296417Sdim MachineBasicBlock::instr_iterator I = MBB.instr_end(); 151296417Sdim unsigned Count = 0; 152296417Sdim 153296417Sdim while (I != MBB.instr_begin()) { 154296417Sdim --I; 155341825Sdim if (I->isDebugInstr()) 156296417Sdim continue; 157296417Sdim if (!I->isTerminator()) 158296417Sdim break; 159296417Sdim // Remove the branch. 160296417Sdim I->eraseFromParent(); 161296417Sdim I = MBB.instr_end(); 162296417Sdim ++Count; 163296417Sdim } 164296417Sdim 165296417Sdim return Count; 166296417Sdim} 167296417Sdim 168344779Sdimunsigned WebAssemblyInstrInfo::insertBranch( 169344779Sdim MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 170344779Sdim ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 171314564Sdim assert(!BytesAdded && "code size not handled"); 172314564Sdim 173296417Sdim if (Cond.empty()) { 174296417Sdim if (!TBB) 175296417Sdim return 0; 176296417Sdim 177296417Sdim BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB); 178296417Sdim return 1; 179296417Sdim } 180296417Sdim 181296417Sdim assert(Cond.size() == 2 && "Expected a flag and a successor block"); 182296417Sdim 183296417Sdim if (Cond[0].getImm()) { 184321369Sdim BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]); 185296417Sdim } else { 186321369Sdim BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]); 187296417Sdim } 188296417Sdim if (!FBB) 189296417Sdim return 1; 190296417Sdim 191296417Sdim BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB); 192296417Sdim return 2; 193296417Sdim} 194296417Sdim 195314564Sdimbool WebAssemblyInstrInfo::reverseBranchCondition( 196296417Sdim SmallVectorImpl<MachineOperand> &Cond) const { 197296417Sdim assert(Cond.size() == 2 && "Expected a flag and a successor block"); 198296417Sdim Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm()); 199296417Sdim return false; 200296417Sdim} 201