2015-06-30 07:51:55 +08:00
|
|
|
//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// \brief This file contains the WebAssembly implementation of the
|
|
|
|
/// TargetInstrInfo class.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "WebAssemblyInstrInfo.h"
|
|
|
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
2016-01-28 09:22:44 +08:00
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
2015-06-30 07:51:55 +08:00
|
|
|
#include "WebAssemblySubtarget.h"
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "wasm-instr-info"
|
|
|
|
|
2015-07-23 05:28:15 +08:00
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
|
|
#include "WebAssemblyGenInstrInfo.inc"
|
|
|
|
|
2015-06-30 07:51:55 +08:00
|
|
|
WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
|
2015-12-05 07:22:35 +08:00
|
|
|
: WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
|
|
|
|
WebAssembly::ADJCALLSTACKUP),
|
|
|
|
RI(STI.getTargetTriple()) {}
|
2015-09-09 08:52:47 +08:00
|
|
|
|
2016-01-20 00:59:23 +08:00
|
|
|
bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
|
|
|
|
const MachineInstr *MI, AliasAnalysis *AA) const {
|
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
case WebAssembly::CONST_I32:
|
|
|
|
case WebAssembly::CONST_I64:
|
|
|
|
case WebAssembly::CONST_F32:
|
|
|
|
case WebAssembly::CONST_F64:
|
|
|
|
// isReallyTriviallyReMaterializableGeneric misses these because of the
|
|
|
|
// ARGUMENTS implicit def, so we manualy override it here.
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-09 08:52:47 +08:00
|
|
|
void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
DebugLoc DL, unsigned DestReg,
|
|
|
|
unsigned SrcReg, bool KillSrc) const {
|
2015-12-17 07:21:30 +08:00
|
|
|
// This method is called by post-RA expansion, which expects only pregs to
|
|
|
|
// exist. However we need to handle both here.
|
|
|
|
auto &MRI = MBB.getParent()->getRegInfo();
|
2016-01-20 00:59:23 +08:00
|
|
|
const TargetRegisterClass *RC =
|
|
|
|
TargetRegisterInfo::isVirtualRegister(DestReg)
|
|
|
|
? MRI.getRegClass(DestReg)
|
2016-01-30 02:37:49 +08:00
|
|
|
: MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
|
2015-11-19 00:12:01 +08:00
|
|
|
|
2015-11-24 03:30:43 +08:00
|
|
|
unsigned CopyLocalOpcode;
|
2015-11-19 00:12:01 +08:00
|
|
|
if (RC == &WebAssembly::I32RegClass)
|
2015-11-24 03:30:43 +08:00
|
|
|
CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::I64RegClass)
|
2015-11-24 03:30:43 +08:00
|
|
|
CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F32RegClass)
|
2015-11-24 03:30:43 +08:00
|
|
|
CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F64RegClass)
|
2015-11-24 03:30:43 +08:00
|
|
|
CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64;
|
2015-11-19 00:12:01 +08:00
|
|
|
else
|
|
|
|
llvm_unreachable("Unexpected register class");
|
|
|
|
|
2015-11-24 03:30:43 +08:00
|
|
|
BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg)
|
2015-09-09 08:52:47 +08:00
|
|
|
.addReg(SrcReg, KillSrc ? RegState::Kill : 0);
|
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
|
2016-01-28 09:22:44 +08:00
|
|
|
MachineInstr *
|
|
|
|
WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr *MI, bool NewMI,
|
|
|
|
unsigned OpIdx1,
|
|
|
|
unsigned OpIdx2) const {
|
|
|
|
// If the operands are stackified, we can't reorder them.
|
|
|
|
WebAssemblyFunctionInfo &MFI =
|
|
|
|
*MI->getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
if (MFI.isVRegStackified(MI->getOperand(OpIdx1).getReg()) ||
|
|
|
|
MFI.isVRegStackified(MI->getOperand(OpIdx2).getReg()))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Otherwise use the default implementation.
|
|
|
|
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
|
|
|
}
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
// Branch analysis.
|
|
|
|
bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock *&TBB,
|
|
|
|
MachineBasicBlock *&FBB,
|
|
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
2015-11-30 06:32:02 +08:00
|
|
|
bool /*AllowModify*/) const {
|
2015-09-17 00:51:30 +08:00
|
|
|
bool HaveCond = false;
|
2015-12-22 01:22:02 +08:00
|
|
|
for (MachineInstr &MI : MBB.terminators()) {
|
2015-09-17 00:51:30 +08:00
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
default:
|
|
|
|
// Unhandled instruction; bail out.
|
|
|
|
return true;
|
2015-11-13 08:46:31 +08:00
|
|
|
case WebAssembly::BR_IF:
|
2015-09-17 00:51:30 +08:00
|
|
|
if (HaveCond)
|
|
|
|
return true;
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
// If we're running after CFGStackify, we can't optimize further.
|
2016-02-09 05:50:13 +08:00
|
|
|
if (!MI.getOperand(0).isMBB())
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
return true;
|
2015-12-05 11:03:35 +08:00
|
|
|
Cond.push_back(MachineOperand::CreateImm(true));
|
2016-02-09 05:50:13 +08:00
|
|
|
Cond.push_back(MI.getOperand(1));
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
2015-12-05 11:03:35 +08:00
|
|
|
HaveCond = true;
|
|
|
|
break;
|
|
|
|
case WebAssembly::BR_UNLESS:
|
|
|
|
if (HaveCond)
|
|
|
|
return true;
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
// If we're running after CFGStackify, we can't optimize further.
|
2016-02-09 05:50:13 +08:00
|
|
|
if (!MI.getOperand(0).isMBB())
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
return true;
|
2015-12-05 11:03:35 +08:00
|
|
|
Cond.push_back(MachineOperand::CreateImm(false));
|
2016-02-09 05:50:13 +08:00
|
|
|
Cond.push_back(MI.getOperand(1));
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
2015-09-17 00:51:30 +08:00
|
|
|
HaveCond = true;
|
|
|
|
break;
|
|
|
|
case WebAssembly::BR:
|
[WebAssembly] Make CFG stackification independent of basic-block labels.
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.
Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.
This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.
This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.
llvm-svn: 257505
2016-01-13 03:14:46 +08:00
|
|
|
// If we're running after CFGStackify, we can't optimize further.
|
|
|
|
if (!MI.getOperand(0).isMBB())
|
|
|
|
return true;
|
2015-09-17 00:51:30 +08:00
|
|
|
if (!HaveCond)
|
|
|
|
TBB = MI.getOperand(0).getMBB();
|
|
|
|
else
|
|
|
|
FBB = MI.getOperand(0).getMBB();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (MI.isBarrier())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
|
|
|
MachineBasicBlock::instr_iterator I = MBB.instr_end();
|
|
|
|
unsigned Count = 0;
|
|
|
|
|
|
|
|
while (I != MBB.instr_begin()) {
|
|
|
|
--I;
|
|
|
|
if (I->isDebugValue())
|
|
|
|
continue;
|
|
|
|
if (!I->isTerminator())
|
|
|
|
break;
|
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
|
|
|
I = MBB.instr_end();
|
|
|
|
++Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2015-11-30 06:32:02 +08:00
|
|
|
unsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock *TBB,
|
|
|
|
MachineBasicBlock *FBB,
|
|
|
|
ArrayRef<MachineOperand> Cond,
|
|
|
|
DebugLoc DL) const {
|
2015-09-17 00:51:30 +08:00
|
|
|
if (Cond.empty()) {
|
|
|
|
if (!TBB)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-12-05 11:03:35 +08:00
|
|
|
assert(Cond.size() == 2 && "Expected a flag and a successor block");
|
|
|
|
|
|
|
|
if (Cond[0].getImm()) {
|
2016-02-09 05:50:13 +08:00
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).addOperand(Cond[1]);
|
2015-12-05 11:03:35 +08:00
|
|
|
} else {
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS))
|
2016-02-09 05:50:13 +08:00
|
|
|
.addMBB(TBB)
|
|
|
|
.addOperand(Cond[1]);
|
2015-12-05 11:03:35 +08:00
|
|
|
}
|
2015-09-17 00:51:30 +08:00
|
|
|
if (!FBB)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WebAssemblyInstrInfo::ReverseBranchCondition(
|
|
|
|
SmallVectorImpl<MachineOperand> &Cond) const {
|
2015-12-05 11:03:35 +08:00
|
|
|
assert(Cond.size() == 2 && "Expected a flag and a successor block");
|
|
|
|
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
|
|
|
|
return false;
|
2015-09-17 00:51:30 +08:00
|
|
|
}
|