diff options
| author | Dan Gohman <dan433584@gmail.com> | 2016-10-24 19:49:43 +0000 |
|---|---|---|
| committer | Dan Gohman <dan433584@gmail.com> | 2016-10-24 19:49:43 +0000 |
| commit | 4fc4e42dea2547f40d3672ccf473fc2fbbdfc903 (patch) | |
| tree | ebcc8d0e10c97409e41a89e296db5aca2f0ce7fc /llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td | |
| parent | c3e0ce8f8527d340c168d7361c1c59d8df544ecb (diff) | |
| download | bcm5719-llvm-4fc4e42dea2547f40d3672ccf473fc2fbbdfc903.tar.gz bcm5719-llvm-4fc4e42dea2547f40d3672ccf473fc2fbbdfc903.zip | |
[WebAssembly] Add an option to make get_local/set_local explicit.
This patch adds a pass, controlled by an option and off by default for
now, for making implicit get_local/set_local explicit. This simplifies
emitting wasm with MC.
Differential Revision: https://reviews.llvm.org/D25836
llvm-svn: 285009
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td')
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index a316a74fdd2..f774e90d22f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -71,6 +71,9 @@ let OperandNamespace = "WebAssembly" in { let OperandType = "OPERAND_BASIC_BLOCK" in def bb_op : Operand<OtherVT>; +let OperandType = "OPERAND_LOCAL" in +def local_op : Operand<i32>; + let OperandType = "OPERAND_I32IMM" in def i32imm_op : Operand<i32>; @@ -133,20 +136,42 @@ let Defs = [ARGUMENTS] in { // are implied by virtual register uses and defs. multiclass LOCAL<WebAssemblyRegClass vt> { let hasSideEffects = 0 in { - // 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">; - - // TEE_LOCAL is similar to COPY_LOCAL, but writes two copies of its result. - // Typically this would be used to stackify one result and write the other - // result to a local. - let isAsCheapAsAMove = 1 in - def TEE_LOCAL_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), [], - "tee_local\t$res, $also, $src">; + // COPY is not an actual instruction in wasm, but since we allow get_local and + // set_local to be implicit during most of codegen, we can have a COPY which + // is actually a no-op because all the work is done in the implied get_local + // and set_local. COPYs are eliminated (and replaced with + // get_local/set_local) in the ExplicitLocals pass. + let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in + def COPY_#vt : I<(outs vt:$res), (ins vt:$src), [], "copy_local\t$res, $src">; + + // TEE is similar to COPY, but writes two copies of its result. Typically + // this would be used to stackify one result and write the other result to a + // local. + let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in + def TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), [], + "tee_local\t$res, $also, $src">; + + // This is the actual get_local instruction in wasm. These are made explicit + // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm + // local, which is a side effect not otherwise modeled in LLVM. + let mayLoad = 1, isAsCheapAsAMove = 1 in + def GET_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local), [], + "get_local\t$res, $local", 0x14>; + + // This is the actual set_local instruction in wasm. These are made explicit + // by the ExplicitLocals pass. It has mayStore because it writes to a wasm + // local, which is a side effect not otherwise modeled in LLVM. + let mayStore = 1, isAsCheapAsAMove = 1 in + def SET_LOCAL_#vt : I<(outs), (ins local_op:$local, vt:$src), [], + "set_local\t$local, $src", 0x15>; + + // This is the actual tee_local instruction in wasm. TEEs are turned into + // TEE_LOCALs by the ExplicitLocals pass. It has mayStore for the same reason + // as SET_LOCAL. + let mayStore = 1, isAsCheapAsAMove = 1 in + def TEE_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src), [], + "tee_local\t$res, $local, $src", 0x19>; + } // hasSideEffects = 0 } defm : LOCAL<I32>; @@ -155,19 +180,26 @@ defm : LOCAL<F32>; defm : LOCAL<F64>; defm : LOCAL<V128>, Requires<[HasSIMD128]>; +// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates. +// Set TSFlags{2} to 1 to indicate that the immediates are ValTypes. +def DECLARE_LOCALS : I<(outs), (ins variable_ops), [], ".local \t"> { + let TSFlags{0} = 1; + let TSFlags{2} = 1; +} + let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), [(set I32:$res, imm:$imm)], - "i32.const\t$res, $imm">; + "i32.const\t$res, $imm", 0x10>; def CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm), [(set I64:$res, imm:$imm)], - "i64.const\t$res, $imm">; + "i64.const\t$res, $imm", 0x11>; def CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm), [(set F32:$res, fpimm:$imm)], - "f32.const\t$res, $imm">; + "f32.const\t$res, $imm", 0x13>; def CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm), [(set F64:$res, fpimm:$imm)], - "f64.const\t$res, $imm">; + "f64.const\t$res, $imm", 0x12>; } // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 } // Defs = [ARGUMENTS] |

