summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td12
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td9
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td8
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td16
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp38
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td5
10 files changed, 66 insertions, 38 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 405a2a977a0..5a3e02133f5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -377,6 +377,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
if (IsVarArg)
fail(DL, DAG, "WebAssembly doesn't support varargs yet");
+ // Set up the incoming ARGUMENTS value, which serves to represent the liveness
+ // of the incoming values before they're represented by virtual registers.
+ MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
+
for (const ISD::InputArg &In : Ins) {
if (In.Flags.isByVal())
fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
index 530411b147d..4028460bd23 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
@@ -12,6 +12,8 @@
///
//===----------------------------------------------------------------------===//
+let Defs = [ARGUMENTS] in {
+
// The call sequence start/end LLVM-isms isn't useful to WebAssembly since it's
// a virtual ISA.
let isCodeGenOnly = 1 in {
@@ -42,3 +44,5 @@ let Uses = [SP32, SP64], isCall = 1 in {
[(WebAssemblycall0 I32:$callee)],
"call_indirect\t$callee">;
} // Uses = [SP32,SP64], isCall = 1
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
index 7fa4c5613e9..840f7d66931 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
@@ -12,6 +12,8 @@
///
//===----------------------------------------------------------------------===//
+let Defs = [ARGUMENTS] in {
+
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in {
def BR_IF : I<(outs), (ins I32:$a, bb_op:$dst),
[(brcond I32:$a, bb:$dst)],
@@ -59,3 +61,5 @@ let isReturn = 1 in {
} // isReturn = 1
def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
index a4ae5fe7c6d..a34916eb5a2 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
@@ -13,6 +13,8 @@
///
//===----------------------------------------------------------------------===//
+let Defs = [ARGUMENTS] in {
+
def I32_WRAP_I64 : I<(outs I32:$dst), (ins I64:$src),
[(set I32:$dst, (trunc I64:$src))],
"i32.wrap/i64\t$dst, $src">;
@@ -93,3 +95,5 @@ def I64_REINTERPRET_F64 : I<(outs I64:$dst), (ins F64:$src),
def F64_REINTERPRET_I64 : I<(outs F64:$dst), (ins I64:$src),
[(set F64:$dst, (bitconvert I64:$src))],
"f64.reinterpret/i64\t$dst, $src">;
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
index 33efbb350cb..a24c8bfdef3 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
@@ -12,6 +12,8 @@
///
//===----------------------------------------------------------------------===//
+let Defs = [ARGUMENTS] in {
+
defm ADD : BinaryFP<fadd, "add ">;
defm SUB : BinaryFP<fsub, "sub ">;
defm MUL : BinaryFP<fmul, "mul ">;
@@ -30,10 +32,14 @@ defm FLOOR : UnaryFP<ffloor, "floor">;
defm TRUNC : UnaryFP<ftrunc, "trunc">;
defm NEAREST : UnaryFP<fnearbyint, "nearest">;
+} // Defs = [ARGUMENTS]
+
// WebAssembly doesn't expose inexact exceptions, so map frint to fnearbyint.
def : Pat<(frint f32:$src), (NEAREST_F32 f32:$src)>;
def : Pat<(frint f64:$src), (NEAREST_F64 f64:$src)>;
+let Defs = [ARGUMENTS] in {
+
defm EQ : ComparisonFP<SETOEQ, "eq ">;
defm NE : ComparisonFP<SETUNE, "ne ">;
defm LT : ComparisonFP<SETOLT, "lt ">;
@@ -41,6 +47,8 @@ defm LE : ComparisonFP<SETOLE, "le ">;
defm GT : ComparisonFP<SETOGT, "gt ">;
defm GE : ComparisonFP<SETOGE, "ge ">;
+} // Defs = [ARGUMENTS]
+
// Don't care floating-point comparisons, supported via other comparisons.
def : Pat<(seteq f32:$lhs, f32:$rhs), (EQ_F32 f32:$lhs, f32:$rhs)>;
def : Pat<(setne f32:$lhs, f32:$rhs), (NE_F32 f32:$lhs, f32:$rhs)>;
@@ -55,9 +63,13 @@ def : Pat<(setle f64:$lhs, f64:$rhs), (LE_F64 f64:$lhs, f64:$rhs)>;
def : Pat<(setgt f64:$lhs, f64:$rhs), (GT_F64 f64:$lhs, f64:$rhs)>;
def : Pat<(setge f64:$lhs, f64:$rhs), (GE_F64 f64:$lhs, f64:$rhs)>;
+let Defs = [ARGUMENTS] in {
+
def SELECT_F32 : I<(outs F32:$dst), (ins I32:$cond, F32:$lhs, F32:$rhs),
[(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))],
"f32.select\t$dst, $cond, $lhs, $rhs">;
def SELECT_F64 : I<(outs F64:$dst), (ins I32:$cond, F64:$lhs, F64:$rhs),
[(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))],
"f64.select\t$dst, $cond, $lhs, $rhs">;
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index e9a16cec33a..52e0bd6e97f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -81,6 +81,7 @@ include "WebAssemblyInstrFormats.td"
//===----------------------------------------------------------------------===//
multiclass ARGUMENT<WebAssemblyRegClass vt> {
+ let hasSideEffects = 1, Uses = [ARGUMENTS] in
def ARGUMENT_#vt : I<(outs vt:$res), (ins i32imm:$argno),
[(set vt:$res, (WebAssemblyargument timm:$argno))]>;
}
@@ -89,6 +90,8 @@ defm : ARGUMENT<I64>;
defm : ARGUMENT<F32>;
defm : ARGUMENT<F64>;
+let Defs = [ARGUMENTS] in {
+
// get_local and set_local are not generated by instruction selection; they
// are implied by virtual register uses and defs in most contexts. However,
// they are explicitly emitted for special purposes.
@@ -125,11 +128,15 @@ def CONST_F64 : I<(outs F64:$res), (ins f64imm:$imm),
[(set F64:$res, fpimm:$imm)],
"f64.const\t$res, $imm">;
+} // Defs = [ARGUMENTS]
+
def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$dst)),
(CONST_I32 tglobaladdr:$dst)>;
def : Pat<(i32 (WebAssemblywrapper texternalsym:$dst)),
(CONST_I32 texternalsym:$dst)>;
+let Defs = [ARGUMENTS] in {
+
def JUMP_TABLE : I<(outs I32:$dst), (ins tjumptable_op:$addr),
[(set I32:$dst, (WebAssemblywrapper tjumptable:$addr))],
"jump_table\t$dst, $addr">;
@@ -139,6 +146,8 @@ def PARAM : I<(outs), (ins variable_ops), [], ".param \t">;
def RESULT : I<(outs), (ins variable_ops), [], ".result \t">;
def LOCAL : I<(outs), (ins variable_ops), [], ".local \t">;
+} // Defs = [ARGUMENTS]
+
//===----------------------------------------------------------------------===//
// Additional sets of instructions.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
index 1d634dfae08..bc00cd6b4f7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
@@ -12,6 +12,8 @@
///
//===----------------------------------------------------------------------===//
+let Defs = [ARGUMENTS] in {
+
// The spaces after the names are for aesthetic purposes only, to make
// operands line up vertically after tab expansion.
defm ADD : BinaryInt<add, "add ">;
@@ -43,15 +45,21 @@ defm CLZ : UnaryInt<ctlz, "clz ">;
defm CTZ : UnaryInt<cttz, "ctz ">;
defm POPCNT : UnaryInt<ctpop, "popcnt">;
+} // Defs = [ARGUMENTS]
+
// Expand the "don't care" operations to supported operations.
def : Pat<(ctlz_zero_undef I32:$src), (CLZ_I32 I32:$src)>;
def : Pat<(ctlz_zero_undef I64:$src), (CLZ_I64 I64:$src)>;
def : Pat<(cttz_zero_undef I32:$src), (CTZ_I32 I32:$src)>;
def : Pat<(cttz_zero_undef I64:$src), (CTZ_I64 I64:$src)>;
+let Defs = [ARGUMENTS] in {
+
def SELECT_I32 : I<(outs I32:$dst), (ins I32:$cond, I32:$lhs, I32:$rhs),
[(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))],
"i32.select\t$dst, $cond, $lhs, $rhs">;
def SELECT_I64 : I<(outs I64:$dst), (ins I32:$cond, I64:$lhs, I64:$rhs),
[(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))],
"i64.select\t$dst, $cond, $lhs, $rhs">;
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
index f0cc02ada65..700a196fa29 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
@@ -22,6 +22,8 @@
// local types. These memory-only types instead zero- or sign-extend into local
// types when loading, and truncate when storing.
+let Defs = [ARGUMENTS] in {
+
// Basic load.
def LOAD_I32 : I<(outs I32:$dst), (ins I32:$addr),
[(set I32:$dst, (load I32:$addr))],
@@ -68,6 +70,8 @@ def LOAD32_U_I64 : I<(outs I64:$dst), (ins I32:$addr),
[(set I64:$dst, (zextloadi32 I32:$addr))],
"i64.load32_u\t$dst, $addr">;
+} // Defs = [ARGUMENTS]
+
// "Don't care" extending load become zero-extending load.
def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 $addr)>;
def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 $addr)>;
@@ -75,6 +79,8 @@ def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 $addr)>;
def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 $addr)>;
def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 $addr)>;
+let Defs = [ARGUMENTS] in {
+
// Basic store.
// Note that we split the patterns out of the instruction definitions because
// WebAssembly's stores return their operand value, and tablegen doesn't like
@@ -90,11 +96,15 @@ def STORE_F32 : I<(outs F32:$dst), (ins I32:$addr, F32:$val), [],
def STORE_F64 : I<(outs F64:$dst), (ins I32:$addr, F64:$val), [],
"f64.store\t$dst, $addr, $val">;
+} // Defs = [ARGUMENTS]
+
def : Pat<(store I32:$val, I32:$addr), (STORE_I32 I32:$addr, I32:$val)>;
def : Pat<(store I64:$val, I32:$addr), (STORE_I64 I32:$addr, I64:$val)>;
def : Pat<(store F32:$val, I32:$addr), (STORE_F32 I32:$addr, F32:$val)>;
def : Pat<(store F64:$val, I32:$addr), (STORE_F64 I32:$addr, F64:$val)>;
+let Defs = [ARGUMENTS] in {
+
// Truncating store.
def STORE8_I32 : I<(outs I32:$dst), (ins I32:$addr, I32:$val), [],
"i32.store8\t$dst, $addr, $val">;
@@ -107,6 +117,8 @@ def STORE16_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
def STORE32_I64 : I<(outs I64:$dst), (ins I32:$addr, I64:$val), [],
"i64.store32\t$dst, $addr, $val">;
+} // Defs = [ARGUMENTS]
+
def : Pat<(truncstorei8 I32:$val, I32:$addr),
(STORE8_I32 I32:$addr, I32:$val)>;
def : Pat<(truncstorei16 I32:$val, I32:$addr),
@@ -118,6 +130,8 @@ def : Pat<(truncstorei16 I64:$val, I32:$addr),
def : Pat<(truncstorei32 I64:$val, I32:$addr),
(STORE32_I64 I32:$addr, I64:$val)>;
+let Defs = [ARGUMENTS] in {
+
// Memory size.
def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins),
[(set I32:$dst, (int_wasm_memory_size))],
@@ -137,3 +151,5 @@ def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta),
[(int_wasm_grow_memory I64:$delta)],
"grow_memory\t$delta">,
Requires<[HasAddr64]>;
+
+} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp
index b497612b54e..9ec66595d8d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp
@@ -19,7 +19,6 @@
#include "WebAssembly.h"
#include "WebAssemblyMachineFunctionInfo.h"
-#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" // for WebAssembly::ARGUMENT_*
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -46,7 +45,6 @@ public:
AU.addRequired<MachineBlockFrequencyInfo>();
AU.addPreserved<MachineBlockFrequencyInfo>();
AU.addPreservedID(MachineDominatorsID);
- AU.addRequired<SlotIndexes>(); // for ARGUMENT fixups
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -96,42 +94,6 @@ bool WebAssemblyRegColoring::runOnMachineFunction(MachineFunction &MF) {
SmallVector<LiveInterval *, 0> SortedIntervals;
SortedIntervals.reserve(NumVRegs);
- // FIXME: If scheduling has moved an ARGUMENT virtual register, move it back,
- // and recompute liveness. This is a temporary hack.
- bool MovedArg = false;
- MachineBasicBlock &EntryMBB = MF.front();
- MachineBasicBlock::iterator InsertPt = EntryMBB.end();
- // Look for the first NonArg instruction.
- for (auto MII = EntryMBB.begin(), MIE = EntryMBB.end(); MII != MIE; ++MII) {
- MachineInstr *MI = MII;
- if (MI->getOpcode() != WebAssembly::ARGUMENT_I32 &&
- MI->getOpcode() != WebAssembly::ARGUMENT_I64 &&
- MI->getOpcode() != WebAssembly::ARGUMENT_F32 &&
- MI->getOpcode() != WebAssembly::ARGUMENT_F64) {
- InsertPt = MII;
- break;
- }
- }
- // Now move any argument instructions later in the block
- // to before our first NonArg instruction.
- for (auto I = InsertPt, E = EntryMBB.end(); I != E; ++I) {
- MachineInstr *MI = I;
- if (MI->getOpcode() == WebAssembly::ARGUMENT_I32 ||
- MI->getOpcode() == WebAssembly::ARGUMENT_I64 ||
- MI->getOpcode() == WebAssembly::ARGUMENT_F32 ||
- MI->getOpcode() == WebAssembly::ARGUMENT_F64) {
- EntryMBB.insert(InsertPt, MI->removeFromParent());
- MovedArg = true;
- }
- }
- if (MovedArg) {
- SlotIndexes &Slots = getAnalysis<SlotIndexes>();
- Liveness->releaseMemory();
- Slots.releaseMemory();
- Slots.runOnMachineFunction(MF);
- Liveness->runOnMachineFunction(MF);
- }
-
DEBUG(dbgs() << "Interesting register intervals:\n");
for (unsigned i = 0; i < NumVRegs; ++i) {
unsigned VReg = TargetRegisterInfo::index2VirtReg(i);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
index 2cf1e38b25b..4057ff7a9b4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
@@ -43,6 +43,11 @@ def F64_0 : WebAssemblyReg<"%f64.0">;
// order uses and defs that must remain in FIFO order.
def EXPR_STACK : WebAssemblyReg<"STACK">;
+// The incoming arguments "register". This is an opaque entity which serves to
+// order the ARGUMENT instructions that are emulating live-in registers and
+// must not be scheduled below other instructions.
+def ARGUMENTS : WebAssemblyReg<"ARGUMENTS">;
+
//===----------------------------------------------------------------------===//
// Register classes
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud