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
|
2018-05-01 23:54:18 +08:00
|
|
|
/// This file contains the WebAssembly implementation of the
|
2015-06-30 07:51:55 +08:00
|
|
|
/// 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] Support instruction selection for catching exceptions
Summary:
This lowers exception catching-related instructions:
1. Lowers `wasm.catch` intrinsic to `catch` instruction
2. Removes `catchpad` and `cleanuppad` instructions; they are not
necessary after isel phase. (`MachineBasicBlock::isEHFuncletEntry()` or
`MachineBasicBlock::isEHPad()` can be used instead.)
3. Lowers `catchret` and `cleanupret` instructions to pseudo `catchret`
and `cleanupret` instructions in isel, which will be replaced with other
instructions in `WebAssemblyExceptionPrepare` pass.
4. Adds 'WebAssemblyExceptionPrepare` pass, which is for running various
transformation for EH. Currently this pass only replaces `catchret` and
`cleanupret` instructions into appropriate wasm instructions to make
this patch successfully run until the end.
Currently this does not handle lowering of intrinsics related to LSDA
info generation (`wasm.landingpad.index` and `wasm.lsda`), because they
cannot be tested without implementing `EHStreamer`'s wasm-specific
handlers. They are marked as TODO, which is needed to make isel pass.
Also this does not generate `try` and `end_try` markers yet, which will
be handled in later patches.
This patch is based on the first wasm EH proposal.
(https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md)
Reviewers: dschuff, majnemer
Subscribers: jfb, sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D44090
llvm-svn: 333705
2018-06-01 06:25:54 +08:00
|
|
|
WebAssembly::ADJCALLSTACKUP,
|
|
|
|
WebAssembly::CATCHRET),
|
2015-12-05 07:22:35 +08:00
|
|
|
RI(STI.getTargetTriple()) {}
|
2015-09-09 08:52:47 +08:00
|
|
|
|
2016-01-20 00:59:23 +08:00
|
|
|
bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
|
2016-06-30 08:01:54 +08:00
|
|
|
const MachineInstr &MI, AliasAnalysis *AA) const {
|
|
|
|
switch (MI.getOpcode()) {
|
2016-01-20 00:59:23 +08:00
|
|
|
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,
|
2016-06-12 23:39:02 +08:00
|
|
|
const DebugLoc &DL, unsigned DestReg,
|
2015-09-09 08:52:47 +08:00
|
|
|
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
|
|
|
|
2016-10-25 03:49:43 +08:00
|
|
|
unsigned CopyOpcode;
|
2015-11-19 00:12:01 +08:00
|
|
|
if (RC == &WebAssembly::I32RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_I32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::I64RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_I64;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F32RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_F32;
|
2015-11-19 00:12:01 +08:00
|
|
|
else if (RC == &WebAssembly::F64RegClass)
|
2016-10-25 03:49:43 +08:00
|
|
|
CopyOpcode = WebAssembly::COPY_F64;
|
2015-11-19 00:12:01 +08:00
|
|
|
else
|
|
|
|
llvm_unreachable("Unexpected register class");
|
|
|
|
|
2016-10-25 03:49:43 +08:00
|
|
|
BuildMI(MBB, I, DL, get(CopyOpcode), 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 *
|
2016-06-30 08:01:54 +08:00
|
|
|
WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
|
2016-01-28 09:22:44 +08:00
|
|
|
unsigned OpIdx1,
|
|
|
|
unsigned OpIdx2) const {
|
|
|
|
// If the operands are stackified, we can't reorder them.
|
|
|
|
WebAssemblyFunctionInfo &MFI =
|
2016-06-30 08:01:54 +08:00
|
|
|
*MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
|
|
|
|
if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
|
|
|
|
MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))
|
2016-01-28 09:22:44 +08:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Otherwise use the default implementation.
|
|
|
|
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
|
|
|
}
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
// Branch analysis.
|
2016-07-15 22:41:04 +08:00
|
|
|
bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
|
2015-09-17 00:51:30 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-09-15 04:43:16 +08:00
|
|
|
unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
|
2016-09-15 01:23:48 +08:00
|
|
|
int *BytesRemoved) const {
|
|
|
|
assert(!BytesRemoved && "code size not handled");
|
|
|
|
|
2015-09-17 00:51:30 +08:00
|
|
|
MachineBasicBlock::instr_iterator I = MBB.instr_end();
|
|
|
|
unsigned Count = 0;
|
|
|
|
|
|
|
|
while (I != MBB.instr_begin()) {
|
|
|
|
--I;
|
2018-05-09 10:42:00 +08:00
|
|
|
if (I->isDebugInstr())
|
2015-09-17 00:51:30 +08:00
|
|
|
continue;
|
|
|
|
if (!I->isTerminator())
|
|
|
|
break;
|
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
|
|
|
I = MBB.instr_end();
|
|
|
|
++Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2016-09-15 01:24:15 +08:00
|
|
|
unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB,
|
2015-11-30 06:32:02 +08:00
|
|
|
MachineBasicBlock *TBB,
|
|
|
|
MachineBasicBlock *FBB,
|
|
|
|
ArrayRef<MachineOperand> Cond,
|
2016-09-15 01:23:48 +08:00
|
|
|
const DebugLoc &DL,
|
|
|
|
int *BytesAdded) const {
|
|
|
|
assert(!BytesAdded && "code size not handled");
|
|
|
|
|
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()) {
|
2017-01-13 17:58:52 +08:00
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]);
|
2015-12-05 11:03:35 +08:00
|
|
|
} else {
|
2017-01-13 17:58:52 +08:00
|
|
|
BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(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;
|
|
|
|
}
|
|
|
|
|
2016-09-15 04:43:16 +08:00
|
|
|
bool WebAssemblyInstrInfo::reverseBranchCondition(
|
2015-09-17 00:51:30 +08:00
|
|
|
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
|
|
|
}
|