[WebAssembly] Use a physical register to describe ARGUMENT liveness.
authorDan Gohman <dan433584@gmail.com>
Wed, 25 Nov 2015 19:36:19 +0000 (19:36 +0000)
committerDan Gohman <dan433584@gmail.com>
Wed, 25 Nov 2015 19:36:19 +0000 (19:36 +0000)
Instead of trying to move ARGUMENT instructions back up to the top after
they've been scheduled or sunk down, use a fake physical register to
create a liveness constraint that prevents ARGUMENT instructions from
moving down in the first place. This is still not entirely ideal, however
it is more robust than letting them move and moving them back.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254084 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
lib/Target/WebAssembly/WebAssemblyInstrCall.td
lib/Target/WebAssembly/WebAssemblyInstrControl.td
lib/Target/WebAssembly/WebAssemblyInstrConv.td
lib/Target/WebAssembly/WebAssemblyInstrFloat.td
lib/Target/WebAssembly/WebAssemblyInstrInfo.td
lib/Target/WebAssembly/WebAssemblyInstrInteger.td
lib/Target/WebAssembly/WebAssemblyInstrMemory.td
lib/Target/WebAssembly/WebAssemblyRegColoring.cpp
lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
test/CodeGen/WebAssembly/dead-vreg.ll

index 405a2a977a0ab1bf6743d0344fb792288a623cd3..5a3e02133f5a4f7ed523f29eb0a83a0f70729d73 100644 (file)
@@ -377,6 +377,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
   if (IsVarArg)
     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
 
   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");
   for (const ISD::InputArg &In : Ins) {
     if (In.Flags.isByVal())
       fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
index 530411b147d82b037a99f69048319a4981ec1ec6..4028460bd231c724aac084eecaa7b6c588f48b02 100644 (file)
@@ -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 {
 // 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
                              [(WebAssemblycall0 I32:$callee)],
                              "call_indirect\t$callee">;
 } // Uses = [SP32,SP64], isCall = 1
+
+} // Defs = [ARGUMENTS]
index 7fa4c5613e96f24778da191f92d347c14d8e79f9..840f7d669314ac7d9101e66ba9bf0dee43607620 100644 (file)
@@ -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)],
 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
 } // isReturn = 1
   def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
+
+} // Defs = [ARGUMENTS]
index a4ae5fe7c6dc99b4d94f275496aacb50f08aca07..a34916eb5a2d9d7c606c143899f51f448fa90e92 100644 (file)
@@ -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">;
 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">;
 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]
index 33efbb350cba62e9d507b7a4c2bb43b6a4dbdaaf..a24c8bfdef36863848a4cb2371933f5f644254a4 100644 (file)
@@ -12,6 +12,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
 ///
 //===----------------------------------------------------------------------===//
 
+let Defs = [ARGUMENTS] in {
+
 defm ADD : BinaryFP<fadd, "add ">;
 defm SUB : BinaryFP<fsub, "sub ">;
 defm MUL : BinaryFP<fmul, "mul ">;
 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">;
 
 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)>;
 
 // 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  ">;
 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  ">;
 
 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)>;
 // 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)>;
 
 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">;
 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]
index e9a16cec33a8b17151d1ef81628ddd1b39391992..52e0bd6e97f5b588a69ed4a0cafe3f889f8cb9b1 100644 (file)
@@ -81,6 +81,7 @@ include "WebAssemblyInstrFormats.td"
 //===----------------------------------------------------------------------===//
 
 multiclass ARGUMENT<WebAssemblyRegClass vt> {
 //===----------------------------------------------------------------------===//
 
 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))]>;
 }
   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>;
 
 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.
 // 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">;
 
                   [(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)>;
 
 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">;
 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">;
 
 def RESULT : I<(outs), (ins variable_ops), [], ".result \t">;
 def LOCAL  : I<(outs), (ins variable_ops), [], ".local  \t">;
 
+} // Defs = [ARGUMENTS]
+
 //===----------------------------------------------------------------------===//
 // Additional sets of instructions.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // Additional sets of instructions.
 //===----------------------------------------------------------------------===//
index 1d634dfae08b2676d3dac34aca6873e4f0222a59..bc00cd6b4f7f50944501fec8ce99418d767341c6 100644 (file)
@@ -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 ">;
 // 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">;
 
 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)>;
 
 // 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">;
 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]
index f0cc02ada6579f0f3c185102fd6af5525a477aaf..700a196fa29c94bb7b069ae1d3fe68625b248f47 100644 (file)
@@ -22,6 +22,8 @@
 // local types. These memory-only types instead zero- or sign-extend into local
 // types when loading, and truncate when storing.
 
 // 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))],
 // 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">;
 
                      [(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)>;
 // "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)>;
 
 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
 // 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">;
 
 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)>;
 
 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">;
 // 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">;
 
 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),
 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)>;
 
 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))],
 // 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]>;
                         [(int_wasm_grow_memory I64:$delta)],
                         "grow_memory\t$delta">,
                       Requires<[HasAddr64]>;
+
+} // Defs = [ARGUMENTS]
index b497612b54e863ccd6ce42f37acad5f46ed5fb24..9ec66595d8da4aab8a8f34f233d897bcfc3cb874 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "WebAssembly.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 
 #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"
 #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<MachineBlockFrequencyInfo>();
     AU.addPreserved<MachineBlockFrequencyInfo>();
     AU.addPreservedID(MachineDominatorsID);
-    AU.addRequired<SlotIndexes>(); // for ARGUMENT fixups
     MachineFunctionPass::getAnalysisUsage(AU);
   }
 
     MachineFunctionPass::getAnalysisUsage(AU);
   }
 
@@ -96,42 +94,6 @@ bool WebAssemblyRegColoring::runOnMachineFunction(MachineFunction &MF) {
   SmallVector<LiveInterval *, 0> SortedIntervals;
   SortedIntervals.reserve(NumVRegs);
 
   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);
   DEBUG(dbgs() << "Interesting register intervals:\n");
   for (unsigned i = 0; i < NumVRegs; ++i) {
     unsigned VReg = TargetRegisterInfo::index2VirtReg(i);
index 2cf1e38b25b9c11237740c5c0fc65098e8029ec7..4057ff7a9b4348641eea75cfbd57592e71587024 100644 (file)
@@ -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">;
 
 // 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
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 //  Register classes
 //===----------------------------------------------------------------------===//
index e1ae1aecdf217aa7885d19f6e707cb58096aceea..cf1415c1982bff5cc0cc61face72c476e9d6cd02 100644 (file)
@@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown"
 define void @foo(i32* nocapture %a, i32 %w, i32 %h) {
 ; CHECK-LABEL: foo:
 ; CHECK-NEXT: .param i32, i32, i32{{$}}
 define void @foo(i32* nocapture %a, i32 %w, i32 %h) {
 ; CHECK-LABEL: foo:
 ; CHECK-NEXT: .param i32, i32, i32{{$}}
-; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}}
+; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32, i32{{$}}
 entry:
   %cmp.19 = icmp sgt i32 %h, 0
   br i1 %cmp.19, label %for.cond.1.preheader.lr.ph, label %for.end.7
 entry:
   %cmp.19 = icmp sgt i32 %h, 0
   br i1 %cmp.19, label %for.cond.1.preheader.lr.ph, label %for.end.7