Teach the register stackifier to rematerialize constants that have multiple uses instead of leaving them in registers. In the WebAssembly encoding, it's the same code size to materialize most constants as it is to read a value from a register. llvm-svn: 258142
160 lines
6.7 KiB
TableGen
160 lines
6.7 KiB
TableGen
// WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- tablegen -*-
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief WebAssembly Instruction definitions.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WebAssembly Instruction Predicate Definitions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
|
|
def HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
|
|
def HasSIMD128 : Predicate<"Subtarget->hasSIMD128()">,
|
|
AssemblerPredicate<"FeatureSIMD128", "simd128">;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WebAssembly-specific DAG Node Types.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>]>;
|
|
def SDT_WebAssemblyCallSeqEnd :
|
|
SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
|
|
def SDT_WebAssemblyCall0 : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
|
|
def SDT_WebAssemblyCall1 : SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>;
|
|
def SDT_WebAssemblyTableswitch : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
|
|
def SDT_WebAssemblyArgument : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
|
|
def SDT_WebAssemblyReturn : SDTypeProfile<0, -1, []>;
|
|
def SDT_WebAssemblyWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
|
|
SDTCisPtrTy<0>]>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WebAssembly-specific DAG Nodes.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def WebAssemblycallseq_start :
|
|
SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
|
|
[SDNPHasChain, SDNPOutGlue]>;
|
|
def WebAssemblycallseq_end :
|
|
SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
|
|
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
|
|
def WebAssemblycall0 : SDNode<"WebAssemblyISD::CALL0",
|
|
SDT_WebAssemblyCall0,
|
|
[SDNPHasChain, SDNPVariadic]>;
|
|
def WebAssemblycall1 : SDNode<"WebAssemblyISD::CALL1",
|
|
SDT_WebAssemblyCall1,
|
|
[SDNPHasChain, SDNPVariadic]>;
|
|
def WebAssemblytableswitch : SDNode<"WebAssemblyISD::TABLESWITCH",
|
|
SDT_WebAssemblyTableswitch,
|
|
[SDNPHasChain, SDNPVariadic]>;
|
|
def WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
|
|
SDT_WebAssemblyArgument>;
|
|
def WebAssemblyreturn : SDNode<"WebAssemblyISD::RETURN",
|
|
SDT_WebAssemblyReturn, [SDNPHasChain]>;
|
|
def WebAssemblywrapper : SDNode<"WebAssemblyISD::Wrapper",
|
|
SDT_WebAssemblyWrapper>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WebAssembly-specific Operands.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let OperandNamespace = "WebAssembly" in {
|
|
|
|
let OperandType = "OPERAND_BASIC_BLOCK" in
|
|
def bb_op : Operand<OtherVT>;
|
|
|
|
let OperandType = "OPERAND_FPIMM" in {
|
|
def f32imm_op : Operand<f32>;
|
|
def f64imm_op : Operand<f64>;
|
|
} // OperandType = "OPERAND_FPIMM"
|
|
|
|
} // OperandNamespace = "WebAssembly"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WebAssembly Instruction Format Definitions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
include "WebAssemblyInstrFormats.td"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Additional instructions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
multiclass ARGUMENT<WebAssemblyRegClass vt> {
|
|
let hasSideEffects = 1, Uses = [ARGUMENTS], isCodeGenOnly = 1 in
|
|
def ARGUMENT_#vt : I<(outs vt:$res), (ins i32imm:$argno),
|
|
[(set vt:$res, (WebAssemblyargument timm:$argno))]>;
|
|
}
|
|
defm : ARGUMENT<I32>;
|
|
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.
|
|
multiclass LOCAL<WebAssemblyRegClass vt> {
|
|
def GET_LOCAL_#vt : I<(outs vt:$res), (ins i32imm:$regno), [],
|
|
"get_local\t$res, $regno">;
|
|
// TODO: set_local returns its operand value
|
|
def SET_LOCAL_#vt : I<(outs), (ins i32imm:$regno, vt:$src), [],
|
|
"set_local\t$regno, $src">;
|
|
|
|
// COPY_LOCAL is not an actual instruction in wasm, but since we allow
|
|
// get_local and set_local to be implicit, we can have a COPY_LOCAL which
|
|
// is actually a no-op because all the work is done in the implied
|
|
// get_local and set_local.
|
|
let isAsCheapAsAMove = 1 in
|
|
def COPY_LOCAL_#vt : I<(outs vt:$res), (ins vt:$src), [],
|
|
"copy_local\t$res, $src">;
|
|
}
|
|
defm : LOCAL<I32>;
|
|
defm : LOCAL<I64>;
|
|
defm : LOCAL<F32>;
|
|
defm : LOCAL<F64>;
|
|
|
|
let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
|
|
def CONST_I32 : I<(outs I32:$res), (ins i32imm:$imm),
|
|
[(set I32:$res, imm:$imm)],
|
|
"i32.const\t$res, $imm">;
|
|
def CONST_I64 : I<(outs I64:$res), (ins i64imm:$imm),
|
|
[(set I64:$res, imm:$imm)],
|
|
"i64.const\t$res, $imm">;
|
|
def CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
|
|
[(set F32:$res, fpimm:$imm)],
|
|
"f32.const\t$res, $imm">;
|
|
def CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
|
|
[(set F64:$res, fpimm:$imm)],
|
|
"f64.const\t$res, $imm">;
|
|
} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
|
|
|
|
} // Defs = [ARGUMENTS]
|
|
|
|
def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
|
|
(CONST_I32 tglobaladdr:$addr)>;
|
|
def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
|
|
(CONST_I32 texternalsym:$addr)>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Additional sets of instructions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
include "WebAssemblyInstrMemory.td"
|
|
include "WebAssemblyInstrCall.td"
|
|
include "WebAssemblyInstrControl.td"
|
|
include "WebAssemblyInstrInteger.td"
|
|
include "WebAssemblyInstrConv.td"
|
|
include "WebAssemblyInstrFloat.td"
|
|
include "WebAssemblyInstrAtomics.td"
|
|
include "WebAssemblyInstrSIMD.td"
|