Remove legacy WasmGC instructions

Remove old, experimental instructions and type encodings that will not be
shipped as part of WasmGC. Updating the encodings and text format to match the
final spec is left as future work.
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index d9d013b..f82156b 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -568,21 +568,11 @@
     ("i31.get_s",            "makeI31Get(s, true)"),
     ("i31.get_u",            "makeI31Get(s, false)"),
     ("ref.test",             "makeRefTest(s)"),
-    ("ref.test_static",      "makeRefTest(s)"),
     ("ref.cast",             "makeRefCast(s)"),
-    ("ref.cast_static",      "makeRefCast(s)"),
-    ("ref.cast_nop",         "makeRefCastNop(s)"),
-    ("ref.cast_nop_static",  "makeRefCastNop(s)"),
     ("br_on_null",           "makeBrOnNull(s)"),
     ("br_on_non_null",       "makeBrOnNull(s, true)"),
-    ("br_on_cast",           "makeBrOnCast(s, std::nullopt)"),
-    ("br_on_cast_static",    "makeBrOnCast(s, std::nullopt)"),
-    ("br_on_cast_fail",      "makeBrOnCast(s, std::nullopt, true)"),
-    ("br_on_cast_static_fail", "makeBrOnCast(s, std::nullopt, true)"),
-    ("br_on_func",           "makeBrOnCast(s, Type(HeapType::func, NonNullable))"),
-    ("br_on_non_func",       "makeBrOnCast(s, Type(HeapType::func, NonNullable), true)"),
-    ("br_on_i31",            "makeBrOnCast(s, Type(HeapType::i31, NonNullable))"),
-    ("br_on_non_i31",        "makeBrOnCast(s, Type(HeapType::i31, NonNullable), true)"),
+    ("br_on_cast",           "makeBrOnCast(s)"),
+    ("br_on_cast_fail",      "makeBrOnCast(s, true)"),
     ("struct.new",           "makeStructNew(s, false)"),
     ("struct.new_default",   "makeStructNew(s, true)"),
     ("struct.get",           "makeStructGet(s)"),
@@ -604,11 +594,7 @@
     ("array.fill",           "makeArrayFill(s)"),
     ("array.init_data",      "makeArrayInitData(s)"),
     ("array.init_elem",      "makeArrayInitElem(s)"),
-    ("ref.is_func",          "makeRefTest(s, Type(HeapType::func, NonNullable))"),
-    ("ref.is_i31",           "makeRefTest(s, Type(HeapType::i31, NonNullable))"),
     ("ref.as_non_null",      "makeRefAs(s, RefAsNonNull)"),
-    ("ref.as_func",          "makeRefCast(s, Type(HeapType::func, NonNullable))"),
-    ("ref.as_i31",           "makeRefCast(s, Type(HeapType::i31, NonNullable))"),
     ("extern.internalize",   "makeRefAs(s, ExternInternalize)"),
     ("extern.externalize",   "makeRefAs(s, ExternExternalize)"),
     ("string.new_wtf8",      "makeStringNew(s, StringNewWTF8, false)"),
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index dd2ad5c..0b7adf9 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1768,8 +1768,7 @@
                                       BinaryenExpressionRef ref,
                                       BinaryenType type) {
   return static_cast<Expression*>(
-    Builder(*(Module*)module)
-      .makeRefCast((Expression*)ref, Type(type), RefCast::Safety::Safe));
+    Builder(*(Module*)module).makeRefCast((Expression*)ref, Type(type)));
 }
 BinaryenExpressionRef BinaryenBrOn(BinaryenModuleRef module,
                                    BinaryenOp op,
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 772847f..ce7baad 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -117,52 +117,19 @@
                   case 'c': {
                     switch (buf[10]) {
                       case '\0':
-                        if (op == "br_on_cast"sv) { return makeBrOnCast(s, std::nullopt); }
+                        if (op == "br_on_cast"sv) { return makeBrOnCast(s); }
                         goto parse_error;
-                      case '_': {
-                        switch (buf[11]) {
-                          case 'f':
-                            if (op == "br_on_cast_fail"sv) { return makeBrOnCast(s, std::nullopt, true); }
-                            goto parse_error;
-                          case 's': {
-                            switch (buf[17]) {
-                              case '\0':
-                                if (op == "br_on_cast_static"sv) { return makeBrOnCast(s, std::nullopt); }
-                                goto parse_error;
-                              case '_':
-                                if (op == "br_on_cast_static_fail"sv) { return makeBrOnCast(s, std::nullopt, true); }
-                                goto parse_error;
-                              default: goto parse_error;
-                            }
-                          }
-                          default: goto parse_error;
-                        }
-                      }
+                      case '_':
+                        if (op == "br_on_cast_fail"sv) { return makeBrOnCast(s, true); }
+                        goto parse_error;
                       default: goto parse_error;
                     }
                   }
-                  case 'f':
-                    if (op == "br_on_func"sv) { return makeBrOnCast(s, Type(HeapType::func, NonNullable)); }
-                    goto parse_error;
-                  case 'i':
-                    if (op == "br_on_i31"sv) { return makeBrOnCast(s, Type(HeapType::i31, NonNullable)); }
-                    goto parse_error;
                   case 'n': {
                     switch (buf[7]) {
-                      case 'o': {
-                        switch (buf[10]) {
-                          case 'f':
-                            if (op == "br_on_non_func"sv) { return makeBrOnCast(s, Type(HeapType::func, NonNullable), true); }
-                            goto parse_error;
-                          case 'i':
-                            if (op == "br_on_non_i31"sv) { return makeBrOnCast(s, Type(HeapType::i31, NonNullable), true); }
-                            goto parse_error;
-                          case 'n':
-                            if (op == "br_on_non_null"sv) { return makeBrOnNull(s, true); }
-                            goto parse_error;
-                          default: goto parse_error;
-                        }
-                      }
+                      case 'o':
+                        if (op == "br_on_non_null"sv) { return makeBrOnNull(s, true); }
+                        goto parse_error;
                       case 'u':
                         if (op == "br_on_null"sv) { return makeBrOnNull(s); }
                         goto parse_error;
@@ -3008,81 +2975,27 @@
     switch (buf[2]) {
       case 'f': {
         switch (buf[4]) {
-          case 'a': {
-            switch (buf[7]) {
-              case 'f':
-                if (op == "ref.as_func"sv) { return makeRefCast(s, Type(HeapType::func, NonNullable)); }
-                goto parse_error;
-              case 'i':
-                if (op == "ref.as_i31"sv) { return makeRefCast(s, Type(HeapType::i31, NonNullable)); }
-                goto parse_error;
-              case 'n':
-                if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); }
-                goto parse_error;
-              default: goto parse_error;
-            }
-          }
-          case 'c': {
-            switch (buf[8]) {
-              case '\0':
-                if (op == "ref.cast"sv) { return makeRefCast(s); }
-                goto parse_error;
-              case '_': {
-                switch (buf[9]) {
-                  case 'n': {
-                    switch (buf[12]) {
-                      case '\0':
-                        if (op == "ref.cast_nop"sv) { return makeRefCastNop(s); }
-                        goto parse_error;
-                      case '_':
-                        if (op == "ref.cast_nop_static"sv) { return makeRefCastNop(s); }
-                        goto parse_error;
-                      default: goto parse_error;
-                    }
-                  }
-                  case 's':
-                    if (op == "ref.cast_static"sv) { return makeRefCast(s); }
-                    goto parse_error;
-                  default: goto parse_error;
-                }
-              }
-              default: goto parse_error;
-            }
-          }
+          case 'a':
+            if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); }
+            goto parse_error;
+          case 'c':
+            if (op == "ref.cast"sv) { return makeRefCast(s); }
+            goto parse_error;
           case 'e':
             if (op == "ref.eq"sv) { return makeRefEq(s); }
             goto parse_error;
           case 'f':
             if (op == "ref.func"sv) { return makeRefFunc(s); }
             goto parse_error;
-          case 'i': {
-            switch (buf[7]) {
-              case 'f':
-                if (op == "ref.is_func"sv) { return makeRefTest(s, Type(HeapType::func, NonNullable)); }
-                goto parse_error;
-              case 'i':
-                if (op == "ref.is_i31"sv) { return makeRefTest(s, Type(HeapType::i31, NonNullable)); }
-                goto parse_error;
-              case 'n':
-                if (op == "ref.is_null"sv) { return makeRefIsNull(s); }
-                goto parse_error;
-              default: goto parse_error;
-            }
-          }
+          case 'i':
+            if (op == "ref.is_null"sv) { return makeRefIsNull(s); }
+            goto parse_error;
           case 'n':
             if (op == "ref.null"sv) { return makeRefNull(s); }
             goto parse_error;
-          case 't': {
-            switch (buf[8]) {
-              case '\0':
-                if (op == "ref.test"sv) { return makeRefTest(s); }
-                goto parse_error;
-              case '_':
-                if (op == "ref.test_static"sv) { return makeRefTest(s); }
-                goto parse_error;
-              default: goto parse_error;
-            }
-          }
+          case 't':
+            if (op == "ref.test"sv) { return makeRefTest(s); }
+            goto parse_error;
           default: goto parse_error;
         }
       }
@@ -3795,87 +3708,30 @@
                     switch (buf[10]) {
                       case '\0':
                         if (op == "br_on_cast"sv) {
-                          auto ret = makeBrOnCast(ctx, pos, std::nullopt);
+                          auto ret = makeBrOnCast(ctx, pos);
                           CHECK_ERR(ret);
                           return *ret;
                         }
                         goto parse_error;
-                      case '_': {
-                        switch (buf[11]) {
-                          case 'f':
-                            if (op == "br_on_cast_fail"sv) {
-                              auto ret = makeBrOnCast(ctx, pos, std::nullopt, true);
-                              CHECK_ERR(ret);
-                              return *ret;
-                            }
-                            goto parse_error;
-                          case 's': {
-                            switch (buf[17]) {
-                              case '\0':
-                                if (op == "br_on_cast_static"sv) {
-                                  auto ret = makeBrOnCast(ctx, pos, std::nullopt);
-                                  CHECK_ERR(ret);
-                                  return *ret;
-                                }
-                                goto parse_error;
-                              case '_':
-                                if (op == "br_on_cast_static_fail"sv) {
-                                  auto ret = makeBrOnCast(ctx, pos, std::nullopt, true);
-                                  CHECK_ERR(ret);
-                                  return *ret;
-                                }
-                                goto parse_error;
-                              default: goto parse_error;
-                            }
-                          }
-                          default: goto parse_error;
+                      case '_':
+                        if (op == "br_on_cast_fail"sv) {
+                          auto ret = makeBrOnCast(ctx, pos, true);
+                          CHECK_ERR(ret);
+                          return *ret;
                         }
-                      }
+                        goto parse_error;
                       default: goto parse_error;
                     }
                   }
-                  case 'f':
-                    if (op == "br_on_func"sv) {
-                      auto ret = makeBrOnCast(ctx, pos, Type(HeapType::func, NonNullable));
-                      CHECK_ERR(ret);
-                      return *ret;
-                    }
-                    goto parse_error;
-                  case 'i':
-                    if (op == "br_on_i31"sv) {
-                      auto ret = makeBrOnCast(ctx, pos, Type(HeapType::i31, NonNullable));
-                      CHECK_ERR(ret);
-                      return *ret;
-                    }
-                    goto parse_error;
                   case 'n': {
                     switch (buf[7]) {
-                      case 'o': {
-                        switch (buf[10]) {
-                          case 'f':
-                            if (op == "br_on_non_func"sv) {
-                              auto ret = makeBrOnCast(ctx, pos, Type(HeapType::func, NonNullable), true);
-                              CHECK_ERR(ret);
-                              return *ret;
-                            }
-                            goto parse_error;
-                          case 'i':
-                            if (op == "br_on_non_i31"sv) {
-                              auto ret = makeBrOnCast(ctx, pos, Type(HeapType::i31, NonNullable), true);
-                              CHECK_ERR(ret);
-                              return *ret;
-                            }
-                            goto parse_error;
-                          case 'n':
-                            if (op == "br_on_non_null"sv) {
-                              auto ret = makeBrOnNull(ctx, pos, true);
-                              CHECK_ERR(ret);
-                              return *ret;
-                            }
-                            goto parse_error;
-                          default: goto parse_error;
+                      case 'o':
+                        if (op == "br_on_non_null"sv) {
+                          auto ret = makeBrOnNull(ctx, pos, true);
+                          CHECK_ERR(ret);
+                          return *ret;
                         }
-                      }
+                        goto parse_error;
                       case 'u':
                         if (op == "br_on_null"sv) {
                           auto ret = makeBrOnNull(ctx, pos);
@@ -8649,75 +8505,20 @@
     switch (buf[2]) {
       case 'f': {
         switch (buf[4]) {
-          case 'a': {
-            switch (buf[7]) {
-              case 'f':
-                if (op == "ref.as_func"sv) {
-                  auto ret = makeRefCast(ctx, pos, Type(HeapType::func, NonNullable));
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case 'i':
-                if (op == "ref.as_i31"sv) {
-                  auto ret = makeRefCast(ctx, pos, Type(HeapType::i31, NonNullable));
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case 'n':
-                if (op == "ref.as_non_null"sv) {
-                  auto ret = makeRefAs(ctx, pos, RefAsNonNull);
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              default: goto parse_error;
+          case 'a':
+            if (op == "ref.as_non_null"sv) {
+              auto ret = makeRefAs(ctx, pos, RefAsNonNull);
+              CHECK_ERR(ret);
+              return *ret;
             }
-          }
-          case 'c': {
-            switch (buf[8]) {
-              case '\0':
-                if (op == "ref.cast"sv) {
-                  auto ret = makeRefCast(ctx, pos);
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case '_': {
-                switch (buf[9]) {
-                  case 'n': {
-                    switch (buf[12]) {
-                      case '\0':
-                        if (op == "ref.cast_nop"sv) {
-                          auto ret = makeRefCastNop(ctx, pos);
-                          CHECK_ERR(ret);
-                          return *ret;
-                        }
-                        goto parse_error;
-                      case '_':
-                        if (op == "ref.cast_nop_static"sv) {
-                          auto ret = makeRefCastNop(ctx, pos);
-                          CHECK_ERR(ret);
-                          return *ret;
-                        }
-                        goto parse_error;
-                      default: goto parse_error;
-                    }
-                  }
-                  case 's':
-                    if (op == "ref.cast_static"sv) {
-                      auto ret = makeRefCast(ctx, pos);
-                      CHECK_ERR(ret);
-                      return *ret;
-                    }
-                    goto parse_error;
-                  default: goto parse_error;
-                }
-              }
-              default: goto parse_error;
+            goto parse_error;
+          case 'c':
+            if (op == "ref.cast"sv) {
+              auto ret = makeRefCast(ctx, pos);
+              CHECK_ERR(ret);
+              return *ret;
             }
-          }
+            goto parse_error;
           case 'e':
             if (op == "ref.eq"sv) {
               auto ret = makeRefEq(ctx, pos);
@@ -8732,32 +8533,13 @@
               return *ret;
             }
             goto parse_error;
-          case 'i': {
-            switch (buf[7]) {
-              case 'f':
-                if (op == "ref.is_func"sv) {
-                  auto ret = makeRefTest(ctx, pos, Type(HeapType::func, NonNullable));
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case 'i':
-                if (op == "ref.is_i31"sv) {
-                  auto ret = makeRefTest(ctx, pos, Type(HeapType::i31, NonNullable));
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case 'n':
-                if (op == "ref.is_null"sv) {
-                  auto ret = makeRefIsNull(ctx, pos);
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              default: goto parse_error;
+          case 'i':
+            if (op == "ref.is_null"sv) {
+              auto ret = makeRefIsNull(ctx, pos);
+              CHECK_ERR(ret);
+              return *ret;
             }
-          }
+            goto parse_error;
           case 'n':
             if (op == "ref.null"sv) {
               auto ret = makeRefNull(ctx, pos);
@@ -8765,25 +8547,13 @@
               return *ret;
             }
             goto parse_error;
-          case 't': {
-            switch (buf[8]) {
-              case '\0':
-                if (op == "ref.test"sv) {
-                  auto ret = makeRefTest(ctx, pos);
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              case '_':
-                if (op == "ref.test_static"sv) {
-                  auto ret = makeRefTest(ctx, pos);
-                  CHECK_ERR(ret);
-                  return *ret;
-                }
-                goto parse_error;
-              default: goto parse_error;
+          case 't':
+            if (op == "ref.test"sv) {
+              auto ret = makeRefTest(ctx, pos);
+              CHECK_ERR(ret);
+              return *ret;
             }
-          }
+            goto parse_error;
           default: goto parse_error;
         }
       }
diff --git a/src/ir/stack-utils.h b/src/ir/stack-utils.h
index aad13f7..82d1f5a 100644
--- a/src/ir/stack-utils.h
+++ b/src/ir/stack-utils.h
@@ -131,13 +131,13 @@
   //
   // As an example of the first rule, consider this instruction sequence:
   //
-  //   ref.as_func
+  //   ref.cast (ref i31)
   //   drop
   //   i32.add
   //
   // The most specific type you could give this sequence is [i32, i32, anyref]
   // -> [i32]. But it could also be used in a context that expects [i32, i32,
-  // funcref] -> [i32] because ref.as_func can accept funcref or any other
+  // structref] -> [i32] because ref.cast can accept structref or any other
   // subtype of anyref. That's where the contravariance comes from. This
   // instruction sequence could also be used anywhere that expects [f32, i32,
   // i32, anyref] -> [f32, i32] because the f32 simply stays on the stack
@@ -145,7 +145,7 @@
   //
   // For the second rule, consider this sequence:
   //
-  //   ref.as_func
+  //   ref.cast (ref i31)
   //   drop
   //   i32.add
   //   unreachable
diff --git a/src/passes/OptimizeCasts.cpp b/src/passes/OptimizeCasts.cpp
index e4d7b16..50fab8f 100644
--- a/src/passes/OptimizeCasts.cpp
+++ b/src/passes/OptimizeCasts.cpp
@@ -385,10 +385,8 @@
 
     auto refCastIter = finder.refCastToApply.find(curr);
     if (refCastIter != finder.refCastToApply.end()) {
-      currPtr = replaceCurrent(Builder(*getModule())
-                                 .makeRefCast(currPtr,
-                                              refCastIter->second->type,
-                                              refCastIter->second->safety));
+      currPtr = replaceCurrent(
+        Builder(*getModule()).makeRefCast(currPtr, refCastIter->second->type));
     }
 
     auto refAsIter = finder.refAsToApply.find(curr);
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 4407854..965f8b2 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1406,13 +1406,13 @@
   // skipCast do): removing a cast is potentially dangerous, as it removes
   // information from the IR. For example:
   //
-  //  (ref.is_func
-  //    (ref.as_func
+  //  (ref.test (ref i31)
+  //    (ref.cast (ref i31)
   //      (local.get $anyref)))
   //
   // The local has no useful type info here (it is anyref). The cast forces it
-  // to be a function, so we know that if we do not trap then the ref.is will
-  // definitely be 1. But if we removed the ref.as first (which we can do in
+  // to be an i31, so we know that if we do not trap then the ref.test will
+  // definitely be 1. But if we removed the ref.cast first (which we can do in
   // traps-never-happen mode) then we'd not have the type info we need to
   // optimize that way.
   //
@@ -1420,12 +1420,12 @@
   //
   //  * Before removing a cast we should use its type information in the best
   //    way we can. Only after doing so should a cast be removed. In the exmaple
-  //    above, that means first seeing that the ref.is must return 1, and only
-  //    then possibly removing the ref.as.
+  //    above, that means first seeing that the ref.test must return 1, and only
+  //    then possibly removing the ref.cast.
   //  * Do not remove a cast if removing it might remove useful information for
   //    others. For example,
   //
-  //      (ref.cast $A
+  //      (ref.cast (ref null $A)
   //        (ref.as_non_null ..))
   //
   //    If we remove the inner cast then the outer cast becomes nullable. That
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 6740bc8..dee23d6 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2102,14 +2102,10 @@
     if (printUnreachableReplacement(curr)) {
       return;
     }
-    if (curr->safety == RefCast::Unsafe) {
-      printMedium(o, "ref.cast_nop ");
+    if (curr->type.isNullable()) {
+      printMedium(o, "ref.cast null ");
     } else {
-      if (curr->type.isNullable()) {
-        printMedium(o, "ref.cast null ");
-      } else {
-        printMedium(o, "ref.cast ");
-      }
+      printMedium(o, "ref.cast ");
     }
     printHeapType(o, curr->type.getHeapType(), wasm);
   }
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 197126f..dc7741c 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -714,9 +714,6 @@
 
         // First, check for a possible null which would prevent optimizations on
         // null checks.
-        // TODO: Look into using BrOnNonNull here, to replace a br_on_func whose
-        // input is (ref null func) with br_on_non_null (as only the null check
-        // would be needed).
         // TODO: Use the fallthrough to determine in more cases that we
         // definitely have a null.
         auto refType = curr->ref->type;
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 8df9b9a..2317e7d 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -3394,8 +3394,7 @@
       // This unreachable avoids a warning on refType being possibly undefined.
       WASM_UNREACHABLE("bad case");
   }
-  // TODO: Fuzz unsafe casts?
-  return builder.makeRefCast(make(refType), type, RefCast::Safe);
+  return builder.makeRefCast(make(refType), type);
 }
 
 Expression* TranslateToFuzzReader::makeStructGet(Type type) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index c6b3e7b..05cd383 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -389,10 +389,6 @@
   Array = -0x22,    // 0x5e
   Sub = -0x30,      // 0x50
   SubFinal = -0x32, // 0x4e
-  // prototype nominal forms we still parse
-  FuncSubtype = -0x23,   // 0x5d
-  StructSubtype = -0x24, // 0x5c
-  ArraySubtype = -0x25,  // 0x5b
   // isorecursive recursion groups
   Rec = -0x31, // 0x4f
   // block_type
@@ -1108,7 +1104,6 @@
   ArrayGetS = 0x14,
   ArrayGetU = 0x15,
   ArraySet = 0x16,
-  ArrayLenAnnotated = 0x17,
   ArrayCopy = 0x18,
   ArrayLen = 0x19,
   ArrayNewFixed = 0x1a,
@@ -1120,23 +1115,10 @@
   I31GetU = 0x22,
   RefTest = 0x40,
   RefCast = 0x41,
-  BrOnCastLegacy = 0x42,
-  BrOnCastFailLegacy = 0x43,
-  BrOnCastNullLegacy = 0x4a,
-  BrOnCastFailNullLegacy = 0x4b,
   BrOnCast = 0x4e,
   BrOnCastFail = 0x4f,
-  RefTestStatic = 0x44,
-  RefCastStatic = 0x45,
   RefTestNull = 0x48,
   RefCastNull = 0x49,
-  RefCastNop = 0x4c,
-  RefAsFunc = 0x58,
-  RefAsI31 = 0x5a,
-  BrOnFunc = 0x60,
-  BrOnI31 = 0x62,
-  BrOnNonFunc = 0x63,
-  BrOnNonI31 = 0x65,
   ExternInternalize = 0x70,
   ExternExternalize = 0x71,
   ArrayFill = 0x0f,
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index a3bf22f..cb7c5e7 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -876,13 +876,10 @@
     ret->finalize();
     return ret;
   }
-  RefCast* makeRefCast(Expression* ref,
-                       Type type,
-                       RefCast::Safety safety = RefCast::Safe) {
+  RefCast* makeRefCast(Expression* ref, Type type) {
     auto* ret = wasm.allocator.alloc<RefCast>();
     ret->ref = ref;
     ret->type = type;
-    ret->safety = safety;
     ret->finalize();
     return ret;
   }
diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def
index 1d9d624..cd8976f 100644
--- a/src/wasm-delegations-fields.def
+++ b/src/wasm-delegations-fields.def
@@ -648,7 +648,6 @@
   }
   case Expression::Id::RefCastId: {
     DELEGATE_START(RefCast);
-    DELEGATE_FIELD_INT(RefCast, safety);
     DELEGATE_FIELD_CHILD(RefCast, ref);
     DELEGATE_END(RefCast);
     break;
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index f61a500..84299f0 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -287,14 +287,10 @@
   Expression* makeCallRef(Element& s, bool isReturn);
   Expression* makeI31New(Element& s);
   Expression* makeI31Get(Element& s, bool signed_);
-  Expression* makeRefTest(Element& s,
-                          std::optional<Type> castType = std::nullopt);
-  Expression* makeRefCast(Element& s,
-                          std::optional<Type> castType = std::nullopt);
-  Expression* makeRefCastNop(Element& s);
+  Expression* makeRefTest(Element& s);
+  Expression* makeRefCast(Element& s);
   Expression* makeBrOnNull(Element& s, bool onFail = false);
-  Expression*
-  makeBrOnCast(Element& s, std::optional<Type> castType, bool onFail = false);
+  Expression* makeBrOnCast(Element& s, bool onFail = false);
   Expression* makeStructNew(Element& s, bool default_);
   Index getStructIndex(Element& type, Element& field);
   Expression* makeStructGet(Element& s, bool signed_ = false);
diff --git a/src/wasm.h b/src/wasm.h
index c059009..39cc9fb 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1525,11 +1525,6 @@
 
   Expression* ref;
 
-  // Support the unsafe `ref.cast_nop_static` to enable precise cast overhead
-  // measurements.
-  enum Safety { Safe, Unsafe };
-  Safety safety = Safe;
-
   void finalize();
 
   Type& getCastType() { return type; }
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 3ceab82..98e8322 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2256,49 +2256,15 @@
       }
       form = getS32LEB();
     }
-    if (form == BinaryConsts::EncodedType::Func ||
-        form == BinaryConsts::EncodedType::FuncSubtype) {
+    if (form == BinaryConsts::EncodedType::Func) {
       builder[i] = readSignatureDef();
-    } else if (form == BinaryConsts::EncodedType::Struct ||
-               form == BinaryConsts::EncodedType::StructSubtype) {
+    } else if (form == BinaryConsts::EncodedType::Struct) {
       builder[i] = readStructDef();
-    } else if (form == BinaryConsts::EncodedType::Array ||
-               form == BinaryConsts::EncodedType::ArraySubtype) {
+    } else if (form == BinaryConsts::EncodedType::Array) {
       builder[i] = Array(readFieldDef());
     } else {
       throwError("Bad type form " + std::to_string(form));
     }
-    if (form == BinaryConsts::EncodedType::FuncSubtype ||
-        form == BinaryConsts::EncodedType::StructSubtype ||
-        form == BinaryConsts::EncodedType::ArraySubtype) {
-      int64_t super = getS64LEB(); // TODO: Actually s33
-      if (super >= 0) {
-        superIndex = (uint32_t)super;
-      } else {
-        // Validate but otherwise ignore trivial supertypes.
-        HeapType basicSuper;
-        if (!getBasicHeapType(super, basicSuper)) {
-          throwError("Unrecognized supertype " + std::to_string(super));
-        }
-        if (form == BinaryConsts::EncodedType::FuncSubtype) {
-          if (basicSuper != HeapType::func) {
-            throwError(
-              "The only allowed trivial supertype for functions is func");
-          }
-        } else {
-          // Check for "struct" here even if we are parsing an array definition.
-          // This is the old nonstandard "struct_subtype" or "array_subtype"
-          // form of type definitions that used the old "data" type as the
-          // supertype placeholder when there was no nontrivial supertype.
-          // "data" no longer exists, but "struct" has the same encoding it used
-          // to have.
-          if (basicSuper != HeapType::struct_) {
-            throwError("The only allowed trivial supertype for structs and "
-                       "arrays is data");
-          }
-        }
-      }
-    }
     if (superIndex) {
       if (*superIndex > builder.size()) {
         throwError("Out of bounds supertype index " +
@@ -4162,12 +4128,6 @@
       if (maybeVisitStringSliceIter(curr, opcode)) {
         break;
       }
-      if (opcode == BinaryConsts::RefAsFunc ||
-          opcode == BinaryConsts::RefAsI31) {
-        visitRefAsCast((curr = allocator.alloc<RefCast>())->cast<RefCast>(),
-                       opcode);
-        break;
-      }
       if (opcode == BinaryConsts::ExternInternalize ||
           opcode == BinaryConsts::ExternExternalize) {
         visitRefAs((curr = allocator.alloc<RefAs>())->cast<RefAs>(), opcode);
@@ -7011,10 +6971,8 @@
 }
 
 bool WasmBinaryReader::maybeVisitRefTest(Expression*& out, uint32_t code) {
-  if (code == BinaryConsts::RefTestStatic || code == BinaryConsts::RefTest ||
-      code == BinaryConsts::RefTestNull) {
-    bool legacy = code == BinaryConsts::RefTestStatic;
-    auto castType = legacy ? getIndexedHeapType() : getHeapType();
+  if (code == BinaryConsts::RefTest || code == BinaryConsts::RefTestNull) {
+    auto castType = getHeapType();
     auto nullability =
       (code == BinaryConsts::RefTestNull) ? Nullable : NonNullable;
     auto* ref = popNonVoidExpression();
@@ -7024,40 +6982,13 @@
   return false;
 }
 
-void WasmBinaryReader::visitRefAsCast(RefCast* curr, uint32_t code) {
-  // TODO: These instructions are deprecated. Remove them.
-  switch (code) {
-    case BinaryConsts::RefAsFunc:
-      curr->type = Type(HeapType::func, NonNullable);
-      break;
-    case BinaryConsts::RefAsI31:
-      curr->type = Type(HeapType::i31, NonNullable);
-      break;
-    default:
-      WASM_UNREACHABLE("unexpected ref.as*");
-  }
-  curr->ref = popNonVoidExpression();
-  curr->safety = RefCast::Safe;
-  curr->finalize();
-}
-
 bool WasmBinaryReader::maybeVisitRefCast(Expression*& out, uint32_t code) {
-  if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCast ||
-      code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) {
-    bool legacy = code == BinaryConsts::RefCastStatic;
-    auto heapType = legacy ? getIndexedHeapType() : getHeapType();
-    auto* ref = popNonVoidExpression();
-    Nullability nullability;
-    if (legacy) {
-      // Legacy polymorphic behavior.
-      nullability = ref->type.getNullability();
-    } else {
-      nullability = code == BinaryConsts::RefCast ? NonNullable : Nullable;
-    }
-    auto safety =
-      code == BinaryConsts::RefCastNop ? RefCast::Unsafe : RefCast::Safe;
+  if (code == BinaryConsts::RefCast || code == BinaryConsts::RefCastNull) {
+    auto heapType = getHeapType();
+    auto nullability = code == BinaryConsts::RefCast ? NonNullable : Nullable;
     auto type = Type(heapType, nullability);
-    out = Builder(wasm).makeRefCast(ref, type, safety);
+    auto* ref = popNonVoidExpression();
+    out = Builder(wasm).makeRefCast(ref, type);
     return true;
   }
   return false;
@@ -7074,63 +7005,32 @@
       op = BrOnNonNull;
       break;
     case BinaryConsts::BrOnCast:
-    case BinaryConsts::BrOnCastLegacy:
-    case BinaryConsts::BrOnCastNullLegacy:
       op = BrOnCast;
       break;
     case BinaryConsts::BrOnCastFail:
-    case BinaryConsts::BrOnCastFailLegacy:
-    case BinaryConsts::BrOnCastFailNullLegacy:
       op = BrOnCastFail;
       break;
-    case BinaryConsts::BrOnFunc:
-      op = BrOnCast;
-      castType = Type(HeapType::func, NonNullable);
-      break;
-    case BinaryConsts::BrOnNonFunc:
-      op = BrOnCastFail;
-      castType = Type(HeapType::func, NonNullable);
-      break;
-    case BinaryConsts::BrOnI31:
-      op = BrOnCast;
-      castType = Type(HeapType::i31, NonNullable);
-      break;
-    case BinaryConsts::BrOnNonI31:
-      op = BrOnCastFail;
-      castType = Type(HeapType::i31, NonNullable);
-      break;
     default:
       return false;
   }
-  bool hasInputAnnotation =
+  bool isCast =
     code == BinaryConsts::BrOnCast || code == BinaryConsts::BrOnCastFail;
   uint8_t flags = 0;
-  if (hasInputAnnotation) {
+  if (isCast) {
     flags = getInt8();
   }
   auto name = getBreakTarget(getU32LEB()).name;
   auto* ref = popNonVoidExpression();
-  if (op == BrOnCast || op == BrOnCastFail) {
-    Nullability inputNullability, castNullability;
-    HeapType inputHeapType, castHeapType;
-    if (hasInputAnnotation) {
-      inputNullability = (flags & 1) ? Nullable : NonNullable;
-      castNullability = (flags & 2) ? Nullable : NonNullable;
-      inputHeapType = getHeapType();
-    } else {
-      castNullability = (code == BinaryConsts::BrOnCastNullLegacy ||
-                         code == BinaryConsts::BrOnCastFailNullLegacy)
-                          ? Nullable
-                          : NonNullable;
-    }
-    castHeapType = getHeapType();
+  if (isCast) {
+    auto inputNullability = (flags & 1) ? Nullable : NonNullable;
+    auto castNullability = (flags & 2) ? Nullable : NonNullable;
+    auto inputHeapType = getHeapType();
+    auto castHeapType = getHeapType();
     castType = Type(castHeapType, castNullability);
-    if (hasInputAnnotation) {
-      auto inputType = Type(inputHeapType, inputNullability);
-      if (!Type::isSubType(ref->type, inputType)) {
-        throwError(std::string("Invalid reference type for ") +
-                   ((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail"));
-      }
+    auto inputType = Type(inputHeapType, inputNullability);
+    if (!Type::isSubType(ref->type, inputType)) {
+      throwError(std::string("Invalid reference type for ") +
+                 ((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail"));
     }
   }
   out = Builder(wasm).makeBrOn(op, name, ref, castType);
@@ -7288,10 +7188,7 @@
 }
 
 bool WasmBinaryReader::maybeVisitArrayLen(Expression*& out, uint32_t code) {
-  if (code == BinaryConsts::ArrayLenAnnotated) {
-    // Ignore the type annotation and don't bother validating it.
-    getU32LEB();
-  } else if (code != BinaryConsts::ArrayLen) {
+  if (code != BinaryConsts::ArrayLen) {
     return false;
   }
   auto* ref = popNonVoidExpression();
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 9b7a1a9..0115cda 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2841,51 +2841,30 @@
   return ret;
 }
 
-Expression* SExpressionWasmBuilder::makeRefTest(Element& s,
-                                                std::optional<Type> castType) {
+Expression* SExpressionWasmBuilder::makeRefTest(Element& s) {
   int i = 1;
-  if (!castType) {
-    auto nullability = NonNullable;
-    if (s[0]->str().str != "ref.test_static" && s[1]->str().str == "null") {
-      nullability = Nullable;
-      ++i;
-    }
-    auto type = parseHeapType(*s[i++]);
-    castType = Type(type, nullability);
+  auto nullability = NonNullable;
+  if (s[1]->str().str == "null") {
+    nullability = Nullable;
+    ++i;
   }
+  auto type = parseHeapType(*s[i++]);
+  auto castType = Type(type, nullability);
   auto* ref = parseExpression(*s[i++]);
-  return Builder(wasm).makeRefTest(ref, *castType);
+  return Builder(wasm).makeRefTest(ref, castType);
 }
 
-Expression* SExpressionWasmBuilder::makeRefCast(Element& s,
-                                                std::optional<Type> castType) {
+Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
   int i = 1;
-  bool legacy = false;
-  if (!castType) {
-    Nullability nullability = NonNullable;
-    if (s[0]->str().str == "ref.cast_static") {
-      legacy = true;
-    } else if (s[i]->str().str == "null") {
-      nullability = Nullable;
-      ++i;
-    }
-    auto type = parseHeapType(*s[i++]);
-    castType = Type(type, nullability);
+  Nullability nullability = NonNullable;
+  if (s[i]->str().str == "null") {
+    nullability = Nullable;
+    ++i;
   }
+  auto type = parseHeapType(*s[i++]);
+  auto castType = Type(type, nullability);
   auto* ref = parseExpression(*s[i++]);
-  if (legacy) {
-    // Legacy polymorphic behavior.
-    castType = Type(castType->getHeapType(), ref->type.getNullability());
-  }
-  return Builder(wasm).makeRefCast(ref, *castType, RefCast::Safe);
-}
-
-Expression* SExpressionWasmBuilder::makeRefCastNop(Element& s) {
-  auto heapType = parseHeapType(*s[1]);
-  auto* ref = parseExpression(*s[2]);
-  // Legacy polymorphic behavior.
-  auto type = Type(heapType, ref->type.getNullability());
-  return Builder(wasm).makeRefCast(ref, type, RefCast::Unsafe);
+  return Builder(wasm).makeRefCast(ref, castType);
 }
 
 Expression* SExpressionWasmBuilder::makeBrOnNull(Element& s, bool onFail) {
@@ -2896,23 +2875,18 @@
   return Builder(wasm).makeBrOn(op, name, ref);
 }
 
-Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s,
-                                                 std::optional<Type> castType,
-                                                 bool onFail) {
+Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s, bool onFail) {
   int i = 1;
   auto name = getLabel(*s[i++]);
-  std::optional<Type> inputType;
-  if (!castType) {
-    inputType = elementToType(*s[i++]);
-    castType = elementToType(*s[i++]);
-  }
+  auto inputType = elementToType(*s[i++]);
+  auto castType = elementToType(*s[i++]);
   auto* ref = parseExpression(*s[i]);
-  if (inputType && !Type::isSubType(ref->type, *inputType)) {
+  if (!Type::isSubType(ref->type, inputType)) {
     throw ParseException(
       "br_on_cast* ref type does not match expected type", s.line, s.col);
   }
   auto op = onFail ? BrOnCastFail : BrOnCast;
-  return Builder(wasm).makeBrOn(op, name, ref, *castType);
+  return Builder(wasm).makeBrOn(op, name, ref, castType);
 }
 
 Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index ee457da..3b77569 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2021,17 +2021,12 @@
 
 void BinaryInstWriter::visitRefCast(RefCast* curr) {
   o << int8_t(BinaryConsts::GCPrefix);
-  if (curr->safety == RefCast::Unsafe) {
-    o << U32LEB(BinaryConsts::RefCastNop);
-    parent.writeHeapType(curr->type.getHeapType());
+  if (curr->type.isNullable()) {
+    o << U32LEB(BinaryConsts::RefCastNull);
   } else {
-    if (curr->type.isNullable()) {
-      o << U32LEB(BinaryConsts::RefCastNull);
-    } else {
-      o << U32LEB(BinaryConsts::RefCast);
-    }
-    parent.writeHeapType(curr->type.getHeapType());
+    o << U32LEB(BinaryConsts::RefCast);
   }
+  parent.writeHeapType(curr->type.getHeapType());
 }
 
 void BinaryInstWriter::visitBrOn(BrOn* curr) {
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 528d0d1..d5bda85 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -2374,18 +2374,12 @@
 template<typename Ctx> Result<typename Ctx::InstrT> makeI31New(Ctx&, Index);
 template<typename Ctx>
 Result<typename Ctx::InstrT> makeI31Get(Ctx&, Index, bool signed_);
-template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeRefTest(Ctx&, Index, std::optional<Type> castType = std::nullopt);
-template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeRefCast(Ctx&, Index, std::optional<Type> castType = std::nullopt);
-template<typename Ctx> Result<typename Ctx::InstrT> makeRefCastNop(Ctx&, Index);
+template<typename Ctx> Result<typename Ctx::InstrT> makeRefTest(Ctx&, Index);
+template<typename Ctx> Result<typename Ctx::InstrT> makeRefCast(Ctx&, Index);
 template<typename Ctx>
 Result<typename Ctx::InstrT> makeBrOnNull(Ctx&, Index, bool onFail = false);
 template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeBrOnCast(Ctx&, Index, std::optional<Type>, bool onFail = false);
+Result<typename Ctx::InstrT> makeBrOnCast(Ctx&, Index, bool onFail = false);
 template<typename Ctx>
 Result<typename Ctx::InstrT> makeStructNew(Ctx&, Index, bool default_);
 template<typename Ctx>
@@ -3480,19 +3474,12 @@
 }
 
 template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeRefTest(Ctx& ctx, Index pos, std::optional<Type> castType) {
+Result<typename Ctx::InstrT> makeRefTest(Ctx& ctx, Index pos) {
   return ctx.in.err("unimplemented instruction");
 }
 
 template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeRefCast(Ctx& ctx, Index pos, std::optional<Type> castType) {
-  return ctx.in.err("unimplemented instruction");
-}
-
-template<typename Ctx>
-Result<typename Ctx::InstrT> makeRefCastNop(Ctx& ctx, Index pos) {
+Result<typename Ctx::InstrT> makeRefCast(Ctx& ctx, Index pos) {
   return ctx.in.err("unimplemented instruction");
 }
 
@@ -3502,8 +3489,7 @@
 }
 
 template<typename Ctx>
-Result<typename Ctx::InstrT>
-makeBrOnCast(Ctx& ctx, Index pos, std::optional<Type> castType, bool onFail) {
+Result<typename Ctx::InstrT> makeBrOnCast(Ctx& ctx, Index pos, bool onFail) {
   return ctx.in.err("unimplemented instruction");
 }
 
diff --git a/test/heap-types.wast b/test/heap-types.wast
deleted file mode 100644
index 1d297f8..0000000
--- a/test/heap-types.wast
+++ /dev/null
@@ -1,334 +0,0 @@
-;; Test that we can roundtrip struct and array types
-(module
-  ;; Structs
-  (type $struct.A (struct
-    i32
-    (field f32)
-    (field $named f64)
-  ))
-  ;; identical to $struct.A, so will be canonicalized with it, but field names
-  ;; are different
-  (type $struct.A.prime (struct
-    i32
-    (field f32)
-    (field $othername f64)
-  ))
-  (type $struct.B (struct
-    (field i8)
-    (field (mut i16))
-    (field (ref $struct.A))
-    (field (mut (ref $struct.A)))
-  ))
-  (type $struct.C (struct
-    (field $named-mut (mut f32))
-  ))
-
-  ;; Arrays
-  (type $vector (array (mut f64)))
-  (type $matrix (array (mut (ref null $vector))))
-  (type $bytes (array (mut i8)))
-  (type $words (array (mut i32)))
-
-  (type $parent (struct))
-  (type $child (struct_subtype i32 $parent))
-  (type $grandchild (struct_subtype i32 i64 $child))
-
-  (type $nested-child-struct (struct (field (mut (ref $child)))))
-  (type $nested-child-array (array (mut (ref $child))))
-
-  (global $struct.new-in-global (ref $struct.A)
-    (struct.new_default $struct.A)
-  )
-
-  (func $structs (param $x (ref $struct.A)) (param $struct.A.prime (ref null $struct.A.prime)) (param $grandchild (ref null $grandchild)) (param $struct.C (ref null $struct.C)) (param $nested-child-struct (ref null $nested-child-struct)) (result (ref $struct.B))
-    (local $tA (ref null $struct.A))
-    (local $tB (ref null $struct.B))
-    (local $tc (ref null $struct.C))
-    (local $tv (ref null $vector))
-    (local $tm (ref null $matrix))
-    (drop
-      (local.get $x)
-    )
-    (drop
-      (struct.get $struct.A 0 (local.get $x))
-    )
-    (drop
-      (struct.get $struct.A 1 (local.get $x))
-    )
-    (drop
-      (struct.get $struct.A 2 (local.get $x))
-    )
-    (drop
-      (struct.get $struct.A $named (local.get $x))
-    )
-    (drop
-      (struct.get $struct.A.prime $othername (local.get $struct.A.prime))
-    )
-    (drop
-      (struct.get_u $struct.B 0 (local.get $tB))
-    )
-    (drop
-      (struct.get_s $struct.B 0 (local.get $tB))
-    )
-    ;; immutable fields allow subtyping.
-    (drop
-      (struct.get $child 0 (local.get $grandchild))
-    )
-    (drop
-      (block (result (ref null $struct.A))
-        (local.get $x)
-      )
-    )
-    (drop
-      (if (result (ref null $struct.A))
-        (i32.const 1)
-        (local.get $x)
-        (local.get $x)
-      )
-    )
-    (drop
-      (loop (result (ref null $struct.A))
-        (local.get $x)
-      )
-    )
-    (drop
-      (select (result (ref null $struct.A))
-        (local.get $x)
-        (local.get $x)
-        (i32.const 1)
-      )
-    )
-    (struct.set $struct.C 0
-      (local.get $struct.C)
-      (f32.const 100)
-    )
-    ;; values may be subtypes
-    (struct.set $nested-child-struct 0
-      (local.get $nested-child-struct)
-      (ref.as_non_null
-       (local.get $grandchild)
-      )
-    )
-    (drop
-      (struct.new_default $struct.A)
-    )
-    (drop
-      (struct.new $struct.A
-        (i32.const 1)
-        (f32.const 2.345)
-        (f64.const 3.14159)
-      )
-    )
-    (unreachable)
-  )
-  (func $arrays (param $x (ref $vector)) (param $nested-child-array (ref null $nested-child-array)) (param $grandchild (ref null $grandchild)) (result (ref $matrix))
-    (local $tv (ref null $vector))
-    (local $tm (ref null $matrix))
-    (local $tb (ref null $bytes))
-    (local $tw (ref null $words))
-    (drop
-      (array.new $vector
-        (f64.const 3.14159)
-        (i32.const 3)
-      )
-    )
-    (drop
-      (array.new_default $matrix
-        (i32.const 10)
-      )
-    )
-    (drop
-      (array.get $vector
-        (local.get $x)
-        (i32.const 2)
-      )
-    )
-    (array.set $vector
-      (local.get $x)
-      (i32.const 2)
-      (f64.const 2.18281828)
-    )
-    ;; values may be subtypes
-    (array.set $nested-child-array
-      (local.get $nested-child-array)
-      (i32.const 3)
-      (ref.as_non_null
-       (local.get $grandchild)
-      )
-    )
-    (drop
-      (array.len $vector
-        (local.get $x)
-      )
-    )
-    (drop
-      (array.get $words
-        (local.get $tw)
-        (i32.const 1)
-      )
-    )
-    (drop
-      (array.get_u $bytes
-        (local.get $tb)
-        (i32.const 2)
-      )
-    )
-    (drop
-      (array.get_s $bytes
-        (local.get $tb)
-        (i32.const 3)
-      )
-    )
-    (unreachable)
-  )
-  (func $ref.is_X (param $x anyref)
-    (if (ref.is_null (local.get $x)) (unreachable))
-    (if (ref.is_i31 (local.get $x)) (unreachable))
-  )
-  (func $ref.as_X (param $x anyref) (param $f funcref)
-    (drop (ref.as_non_null (local.get $x)))
-    (drop (ref.as_func (local.get $f)))
-    (drop (ref.as_i31 (local.get $x)))
-  )
-  (func $br_on_X (param $x anyref)
-    (local $y anyref)
-    (local $z (ref null any))
-    (local $temp-func (ref null func))
-    (local $temp-i31 (ref null i31))
-    (block $null
-      (local.set $z
-        (br_on_null $null (local.get $x))
-      )
-    )
-    (drop
-      (block $i31 (result (ref null i31))
-        (local.set $y
-          (br_on_i31 $i31 (local.get $x))
-        )
-        (ref.null i31)
-      )
-    )
-    (drop
-      (block $non-null (result (ref any))
-        (br_on_non_null $non-null (local.get $x))
-        (unreachable)
-      )
-    )
-    (drop
-      (block $non-i31 (result anyref)
-        (local.set $temp-i31
-          (br_on_non_i31 $non-i31 (local.get $x))
-        )
-        (ref.null any)
-      )
-    )
-  )
-  (func $unreachables-1
-    (drop
-      (struct.get $struct.C 0 (unreachable))
-    )
-  )
-  (func $unreachables-2 (param $struct.C (ref null $struct.C))
-    (struct.set $struct.C 0 (local.get $struct.C) (unreachable))
-  )
-  (func $unreachables-3
-    (struct.set $struct.C 0 (unreachable) (unreachable))
-  )
-  (func $unreachables-4
-    (struct.set $struct.C 0 (unreachable) (f32.const 1))
-  )
-  (func $unreachables-array-1
-    (array.get $vector
-      (unreachable)
-      (i32.const 2)
-    )
-  )
-  (func $unreachables-array-2 (param $vector (ref null $vector))
-    (array.get $vector
-      (local.get $vector)
-      (unreachable)
-    )
-  )
-  (func $unreachables-array-3
-    (array.set $vector
-      (unreachable)
-      (i32.const 2)
-      (f64.const 2.18281828)
-    )
-  )
-  (func $unreachables-array-4 (param $vector (ref null $vector))
-    (array.set $vector
-      (local.get $vector)
-      (unreachable)
-      (f64.const 2.18281828)
-    )
-  )
-  (func $unreachables-array-5 (param $vector (ref null $vector))
-    (array.set $vector
-      (local.get $vector)
-      (i32.const 2)
-      (unreachable)
-    )
-  )
-  (func $unreachables-array-6
-    (drop
-      (array.len $vector
-        (unreachable)
-      )
-    )
-  )
-  (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector))
-    (array.copy $vector $vector
-      (local.get $x)
-      (i32.const 11)
-      (local.get $y)
-      (i32.const 42)
-      (i32.const 1337)
-    )
-  )
-  (func $array-init (result (ref $vector))
-    (array.new_fixed $vector
-      (f64.const 1)
-      (f64.const 2)
-      (f64.const 4)
-      (f64.const 8)
-    )
-  )
-  (func $array-init-packed (result (ref $bytes))
-    (array.new_fixed $bytes
-      (i32.const 4)
-      (i32.const 2)
-      (i32.const 1)
-    )
-  )
-  (func $static-operations
-    (local $temp.A (ref null $struct.A))
-    (local $temp.B (ref null $struct.B))
-    (drop
-      (ref.test $struct.B (ref.null $struct.A))
-    )
-    (drop
-      (ref.cast null $struct.B (ref.null $struct.A))
-    )
-    (drop
-      (block $out-B (result (ref $struct.B))
-        (local.set $temp.A
-          (br_on_cast $out-B (ref null $struct.A) (ref $struct.B)
-            (ref.null $struct.A)
-          )
-        )
-        (unreachable)
-      )
-    )
-    (drop
-      (block $out-A (result (ref null $struct.A))
-        (local.set $temp.B
-          (br_on_cast_fail $out-A (ref null $struct.A) (ref $struct.B)
-            (ref.null $struct.A)
-          )
-        )
-        (unreachable)
-      )
-    )
-  )
-)
diff --git a/test/lit/binary/annotated-array-len.test b/test/lit/binary/annotated-array-len.test
deleted file mode 100644
index 9cf6eec..0000000
--- a/test/lit/binary/annotated-array-len.test
+++ /dev/null
@@ -1,18 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
-
-;; Test the we can properly parse the annotated array.len format that we no
-;; longer emit.
-
-;; RUN: wasm-dis %s.wasm -all | filecheck %s
-
-;; CHECK:      (type $none_=>_i32 (func (result i32)))
-
-;; CHECK:      (type $[mut:i8] (array (mut i8)))
-
-;; CHECK:      (func $0 (type $none_=>_i32) (result i32)
-;; CHECK-NEXT:  (array.len
-;; CHECK-NEXT:   (array.new_default $[mut:i8]
-;; CHECK-NEXT:    (i32.const 0)
-;; CHECK-NEXT:   )
-;; CHECK-NEXT:  )
-;; CHECK-NEXT: )
diff --git a/test/lit/binary/annotated-array-len.test.wasm b/test/lit/binary/annotated-array-len.test.wasm
deleted file mode 100644
index b199f58..0000000
--- a/test/lit/binary/annotated-array-len.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/binary/bad-ref-as.test b/test/lit/binary/bad-ref-as.test
deleted file mode 100644
index 3accdd5..0000000
--- a/test/lit/binary/bad-ref-as.test
+++ /dev/null
@@ -1,5 +0,0 @@
-;; Test that we error properly on a file with a ref.as of a non-ref type.
-
-;; RUN: not wasm-opt -all %s.wasm 2>&1 | filecheck %s
-
-;; CHECK: ref.cast ref must have ref type
diff --git a/test/lit/binary/bad-ref-as.test.wasm b/test/lit/binary/bad-ref-as.test.wasm
deleted file mode 100644
index 637537d..0000000
--- a/test/lit/binary/bad-ref-as.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/legacy-static-casts.wast b/test/lit/legacy-static-casts.wast
deleted file mode 100644
index 893fb0a..0000000
--- a/test/lit/legacy-static-casts.wast
+++ /dev/null
@@ -1,47 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
-
-;; Check that the deprecated *_static instruction names are still parsed correctly.
-
-;; RUN: wasm-opt %s -all -S -o - | filecheck %s
-
-(module
-  ;; CHECK:      (type $none_=>_none (func))
-
-  ;; CHECK:      (type $struct (struct ))
-  (type $struct (struct))
-
-  ;; CHECK:      (func $test (type $none_=>_none)
-  ;; CHECK-NEXT:  (drop
-  ;; CHECK-NEXT:   (ref.test $struct
-  ;; CHECK-NEXT:    (ref.null none)
-  ;; CHECK-NEXT:   )
-  ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT:  (drop
-  ;; CHECK-NEXT:   (ref.cast null none
-  ;; CHECK-NEXT:    (ref.null none)
-  ;; CHECK-NEXT:   )
-  ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT:  (drop
-  ;; CHECK-NEXT:   (ref.cast_nop none
-  ;; CHECK-NEXT:    (ref.null none)
-  ;; CHECK-NEXT:   )
-  ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT: )
-  (func $test
-    (drop
-      (ref.test_static $struct
-        (ref.null none)
-      )
-    )
-    (drop
-      (ref.cast_static $struct
-        (ref.null none)
-      )
-    )
-    (drop
-      (ref.cast_nop_static $struct
-        (ref.null none)
-      )
-    )
-  )
-)
diff --git a/test/lit/passes/abstract-type-refining.wast b/test/lit/passes/abstract-type-refining.wast
index 220de96..af2b210 100644
--- a/test/lit/passes/abstract-type-refining.wast
+++ b/test/lit/passes/abstract-type-refining.wast
@@ -217,11 +217,6 @@
   ;; YESTNH-NEXT:    (local.get $x)
   ;; YESTNH-NEXT:   )
   ;; YESTNH-NEXT:  )
-  ;; YESTNH-NEXT:  (drop
-  ;; YESTNH-NEXT:   (ref.cast i31
-  ;; YESTNH-NEXT:    (local.get $x)
-  ;; YESTNH-NEXT:   )
-  ;; YESTNH-NEXT:  )
   ;; YESTNH-NEXT: )
   ;; NO_TNH:      (func $basic (type $anyref_=>_none) (param $x anyref)
   ;; NO_TNH-NEXT:  (drop
@@ -229,11 +224,6 @@
   ;; NO_TNH-NEXT:    (local.get $x)
   ;; NO_TNH-NEXT:   )
   ;; NO_TNH-NEXT:  )
-  ;; NO_TNH-NEXT:  (drop
-  ;; NO_TNH-NEXT:   (ref.cast i31
-  ;; NO_TNH-NEXT:    (local.get $x)
-  ;; NO_TNH-NEXT:   )
-  ;; NO_TNH-NEXT:  )
   ;; NO_TNH-NEXT: )
   (func $basic (param $x anyref)
     ;; Casts to basic types should not be modified.
@@ -242,11 +232,6 @@
         (local.get $x)
       )
     )
-    (drop
-      (ref.as_i31
-        (local.get $x)
-      )
-    )
   )
 
   ;; YESTNH:      (func $locals (type $none_=>_none)
diff --git a/test/lit/passes/code-pushing-gc.wast b/test/lit/passes/code-pushing-gc.wast
index 56cfc87..9587d5a 100644
--- a/test/lit/passes/code-pushing-gc.wast
+++ b/test/lit/passes/code-pushing-gc.wast
@@ -7,8 +7,8 @@
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (block $out (result (ref func))
   ;; CHECK-NEXT:    (drop
-  ;; CHECK-NEXT:     (br_on_cast $out (ref $none_=>_none) (ref func)
-  ;; CHECK-NEXT:      (ref.func $br_on)
+  ;; CHECK-NEXT:     (br_on_cast $out nullfuncref (ref func)
+  ;; CHECK-NEXT:      (ref.null nofunc)
   ;; CHECK-NEXT:     )
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:    (local.set $x
@@ -28,8 +28,8 @@
         ;; We can push the local.set past the br_on.
         (local.set $x (ref.func $br_on))
         (drop
-          (br_on_func $out
-            (ref.func $br_on)
+          (br_on_cast $out funcref (ref func)
+            (ref.null nofunc)
           )
         )
         (drop
@@ -48,8 +48,8 @@
   ;; CHECK-NEXT:     (ref.func $br_on_no)
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:    (drop
-  ;; CHECK-NEXT:     (br_on_cast $out (ref $none_=>_none) (ref func)
-  ;; CHECK-NEXT:      (ref.func $br_on_no)
+  ;; CHECK-NEXT:     (br_on_cast $out nullfuncref (ref func)
+  ;; CHECK-NEXT:      (ref.null nofunc)
   ;; CHECK-NEXT:     )
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:    (ref.func $br_on_no)
@@ -61,13 +61,13 @@
   ;; CHECK-NEXT: )
   (func $br_on_no
     (local $x (ref null func))
-    ;; We can't push here since the local.get is outside of the loop.
+    ;; We can't push here since the local.get is outside of the block.
     (drop
       (block $out (result (ref func))
         (local.set $x (ref.func $br_on_no))
         (drop
-          (br_on_func $out
-            (ref.func $br_on_no)
+          (br_on_cast $out funcref (ref func)
+            (ref.null nofunc)
           )
         )
         (ref.func $br_on_no)
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index 7c7aa8c..b82fbf1 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -54,7 +54,7 @@
     (ref.is_null
       (loop $loop (result (ref func))
         (nop)
-        (ref.as_func
+        (ref.cast func
           (ref.as_non_null
             (ref.null func)
           )
diff --git a/test/lit/passes/merge-blocks.wast b/test/lit/passes/merge-blocks.wast
index 2b3afa7..02772c9 100644
--- a/test/lit/passes/merge-blocks.wast
+++ b/test/lit/passes/merge-blocks.wast
@@ -34,7 +34,7 @@
    (block $label$1 (result (ref null i31)) ;; this block type must stay, we
                                            ;; cannot remove it due to the br_on
     (drop
-     (br_on_i31 $label$1
+     (br_on_cast $label$1 anyref (ref i31)
       (ref.null any)
      )
     )
diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast
index 831d229..ba603a5 100644
--- a/test/lit/passes/optimize-instructions-gc-tnh.wast
+++ b/test/lit/passes/optimize-instructions-gc-tnh.wast
@@ -127,6 +127,16 @@
   ;; TNH-NEXT:    (local.get $a)
   ;; TNH-NEXT:   )
   ;; TNH-NEXT:  )
+  ;; TNH-NEXT:  (drop
+  ;; TNH-NEXT:   (block (result i32)
+  ;; TNH-NEXT:    (drop
+  ;; TNH-NEXT:     (ref.cast $struct
+  ;; TNH-NEXT:      (local.get $a)
+  ;; TNH-NEXT:     )
+  ;; TNH-NEXT:    )
+  ;; TNH-NEXT:    (i32.const 0)
+  ;; TNH-NEXT:   )
+  ;; TNH-NEXT:  )
   ;; TNH-NEXT:  (ref.is_null
   ;; TNH-NEXT:   (local.get $f)
   ;; TNH-NEXT:  )
@@ -139,6 +149,16 @@
   ;; NO_TNH-NEXT:    )
   ;; NO_TNH-NEXT:   )
   ;; NO_TNH-NEXT:  )
+  ;; NO_TNH-NEXT:  (drop
+  ;; NO_TNH-NEXT:   (block (result i32)
+  ;; NO_TNH-NEXT:    (drop
+  ;; NO_TNH-NEXT:     (ref.cast $struct
+  ;; NO_TNH-NEXT:      (local.get $a)
+  ;; NO_TNH-NEXT:     )
+  ;; NO_TNH-NEXT:    )
+  ;; NO_TNH-NEXT:    (i32.const 0)
+  ;; NO_TNH-NEXT:   )
+  ;; NO_TNH-NEXT:  )
   ;; NO_TNH-NEXT:  (ref.is_null
   ;; NO_TNH-NEXT:   (ref.cast null $void
   ;; NO_TNH-NEXT:    (local.get $f)
@@ -156,39 +176,21 @@
         )
       )
     )
+    ;; If the cast eliminates null, then we can optimize.
+    (drop
+      (ref.is_null
+        (ref.cast $struct
+          (local.get $a)
+        )
+      )
+    )
     ;; It works on func references, too.
     (ref.is_null
       (ref.cast null $void
         (local.get $f)
       )
     )
-  )
 
-  ;; TNH:      (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32)
-  ;; TNH-NEXT:  (drop
-  ;; TNH-NEXT:   (ref.as_non_null
-  ;; TNH-NEXT:    (local.get $a)
-  ;; TNH-NEXT:   )
-  ;; TNH-NEXT:  )
-  ;; TNH-NEXT:  (i32.const 1)
-  ;; TNH-NEXT: )
-  ;; NO_TNH:      (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32)
-  ;; NO_TNH-NEXT:  (drop
-  ;; NO_TNH-NEXT:   (ref.as_non_null
-  ;; NO_TNH-NEXT:    (local.get $a)
-  ;; NO_TNH-NEXT:   )
-  ;; NO_TNH-NEXT:  )
-  ;; NO_TNH-NEXT:  (i32.const 1)
-  ;; NO_TNH-NEXT: )
-  (func $ref.is_func (param $a funcref) (result i32)
-    ;; The check must succeed. We can return 1 here, and drop the rest, with or
-    ;; without TNH (in particular, TNH should not just remove the cast but not
-    ;; return a 1).
-    (ref.is_func
-      (ref.as_func
-        (local.get $a)
-      )
-    )
   )
 
   ;; TNH:      (func $if.arm.null (type $i32_ref|$struct|_=>_none) (param $x i32) (param $ref (ref $struct))
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index 3407048..9f33c55 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -122,8 +122,8 @@
   )
 
   ;; ref.is_null is not needed on a non-nullable value, and if something is
-  ;; a func we don't need that either etc. if we know the result
-  ;; CHECK:      (func $unneeded_is (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
+  ;; cast to its own type, we don't need that either, etc.
+  ;; CHECK:      (func $unneeded_test (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (block (result i32)
   ;; CHECK-NEXT:    (drop
@@ -149,7 +149,7 @@
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  (func $unneeded_is
+  (func $unneeded_test
     (param $struct (ref $struct))
     (param $func (ref func))
     (param $i31 (ref i31))
@@ -157,16 +157,16 @@
       (ref.is_null (local.get $struct))
     )
     (drop
-       (ref.is_func (local.get $func))
+       (ref.test func (local.get $func))
      )
     (drop
-      (ref.is_i31 (local.get $i31))
+      (ref.test i31 (local.get $i31))
     )
   )
 
   ;; similar to $unneeded_is, but the values are nullable. we can at least
   ;; leave just the null check.
-  ;; CHECK:      (func $unneeded_is_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
+  ;; CHECK:      (func $unneeded_test_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (ref.is_null
   ;; CHECK-NEXT:    (local.get $struct)
@@ -187,7 +187,7 @@
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  (func $unneeded_is_null
+  (func $unneeded_test_null
    (param $struct (ref null $struct))
     (param $func (ref null func))
     (param $i31 (ref null i31))
@@ -197,17 +197,17 @@
     ;; This can be optimized to !is_null rather than ref.test func, since we
     ;; know the heap type is what we want, so the only possible issue is a null.
     (drop
-      (ref.is_func (local.get $func))
+      (ref.test func (local.get $func))
     )
     ;; This can be optimized similarly.
     (drop
-      (ref.is_i31 (local.get $i31))
+      (ref.test i31 (local.get $i31))
     )
   )
 
   ;; ref.as_non_null is not needed on a non-nullable value, and if something is
   ;; a func we don't need that either etc., and can just return the value.
-  ;; CHECK:      (func $unneeded_as (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
+  ;; CHECK:      (func $unneeded_cast (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (local.get $struct)
   ;; CHECK-NEXT:  )
@@ -218,7 +218,7 @@
   ;; CHECK-NEXT:   (local.get $i31)
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  (func $unneeded_as
+  (func $unneeded_cast
     (param $struct (ref $struct))
     (param $func (ref func))
     (param $i31 (ref i31))
@@ -226,16 +226,16 @@
       (ref.as_non_null (local.get $struct))
     )
     (drop
-      (ref.as_func (local.get $func))
+      (ref.cast func (local.get $func))
     )
     (drop
-      (ref.as_i31 (local.get $i31))
+      (ref.cast i31 (local.get $i31))
     )
   )
 
-  ;; similar to $unneeded_as, but the values are nullable. we can turn the
+  ;; similar to $unneeded_cast, but the values are nullable. we can turn the
   ;; more specific things into ref.as_non_null.
-  ;; CHECK:      (func $unneeded_as_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
+  ;; CHECK:      (func $unneeded_cast_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (ref.as_non_null
   ;; CHECK-NEXT:    (local.get $struct)
@@ -252,7 +252,7 @@
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  (func $unneeded_as_null
+  (func $unneeded_cast_null
     (param $struct (ref null $struct))
     (param $func (ref null func))
     (param $i31 (ref null i31))
@@ -260,10 +260,10 @@
       (ref.as_non_null (local.get $struct))
     )
     (drop
-      (ref.as_func (local.get $func))
+      (ref.cast func (local.get $func))
     )
     (drop
-      (ref.as_i31 (local.get $i31))
+      (ref.cast i31 (local.get $i31))
     )
   )
 
@@ -285,10 +285,10 @@
   (func $unneeded_unreachability
     ;; unreachable instructions can simply be ignored
     (drop
-      (ref.is_func (unreachable))
+      (ref.test func (unreachable))
     )
     (drop
-      (ref.as_func (unreachable))
+      (ref.cast func (unreachable))
     )
   )
 
@@ -617,7 +617,7 @@
     ;; This will trap, so we can emit an unreachable.
     (drop
       (ref.cast $struct
-        (ref.as_i31
+        (ref.cast i31
           (local.get $x)
         )
       )
diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast
index e063fa4..50ffd95 100644
--- a/test/lit/passes/remove-unused-brs-gc.wast
+++ b/test/lit/passes/remove-unused-brs-gc.wast
@@ -11,57 +11,6 @@
   (type $struct2 (struct))
  )
 
- ;; CHECK:      (func $br_on_non_i31-1 (type $none_=>_none)
- ;; CHECK-NEXT:  (drop
- ;; CHECK-NEXT:   (block $any (result (ref null $struct))
- ;; CHECK-NEXT:    (drop
- ;; CHECK-NEXT:     (br $any
- ;; CHECK-NEXT:      (struct.new_default $struct)
- ;; CHECK-NEXT:     )
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (ref.null none)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $br_on_non_i31-1
-  (drop
-   (block $any (result anyref)
-    (drop
-     ;; An struct is not an i31, and so we should branch.
-     (br_on_non_i31 $any
-      (struct.new $struct)
-     )
-    )
-    (ref.null any)
-   )
-  )
- )
- ;; CHECK:      (func $br_on_non_i31-2 (type $none_=>_none)
- ;; CHECK-NEXT:  (drop
- ;; CHECK-NEXT:   (block $any (result nullref)
- ;; CHECK-NEXT:    (drop
- ;; CHECK-NEXT:     (i31.new
- ;; CHECK-NEXT:      (i32.const 0)
- ;; CHECK-NEXT:     )
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (ref.null none)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $br_on_non_i31-2
-  (drop
-   (block $any (result anyref)
-    (drop
-     ;; An i31 is provided here, and so we will not branch.
-     (br_on_non_i31 $any
-      (i31.new (i32.const 0))
-     )
-    )
-    (ref.null any)
-   )
-  )
- )
-
  ;; CHECK:      (func $br_on-if (type $ref|struct|_=>_none) (param $0 (ref struct))
  ;; CHECK-NEXT:  (block $label
  ;; CHECK-NEXT:   (drop
@@ -93,34 +42,6 @@
   )
  )
 
- ;; CHECK:      (func $nested_br_on (type $none_=>_i31ref) (result i31ref)
- ;; CHECK-NEXT:  (block $label$1 (result (ref i31))
- ;; CHECK-NEXT:   (drop
- ;; CHECK-NEXT:    (br $label$1
- ;; CHECK-NEXT:     (i31.new
- ;; CHECK-NEXT:      (i32.const 0)
- ;; CHECK-NEXT:     )
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:   (unreachable)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $nested_br_on (result i31ref)
-  (block $label$1 (result i31ref)
-   (drop
-    ;; The inner br_on_i31 will become a direct br since the type proves it
-    ;; is in fact data. That then becomes unreachable, and the parent must
-    ;; handle that properly (do nothing without hitting an assertion).
-    (br_on_i31 $label$1
-     (br_on_i31 $label$1
-      (i31.new (i32.const 0))
-     )
-    )
-   )
-   (unreachable)
-  )
- )
-
  ;; CHECK:      (func $br_on_cast (type $none_=>_ref|$struct|) (result (ref $struct))
  ;; CHECK-NEXT:  (block $block (result (ref $struct))
  ;; CHECK-NEXT:   (drop
@@ -144,6 +65,34 @@
   )
  )
 
+ ;; CHECK:      (func $nested_br_on_cast (type $none_=>_i31ref) (result i31ref)
+ ;; CHECK-NEXT:  (block $label$1 (result (ref i31))
+ ;; CHECK-NEXT:   (drop
+ ;; CHECK-NEXT:    (br $label$1
+ ;; CHECK-NEXT:     (i31.new
+ ;; CHECK-NEXT:      (i32.const 0)
+ ;; CHECK-NEXT:     )
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
+ ;; CHECK-NEXT:   (unreachable)
+ ;; CHECK-NEXT:  )
+ ;; CHECK-NEXT: )
+ (func $nested_br_on_cast (result i31ref)
+  (block $label$1 (result i31ref)
+   (drop
+    ;; The inner br_on_cast will become a direct br since the type proves it
+    ;; is in fact i31. That then becomes unreachable, and the parent must
+    ;; handle that properly (do nothing without hitting an assertion).
+    (br_on_cast $label$1 (ref any) (ref i31)
+     (br_on_cast $label$1 (ref any) (ref i31)
+      (i31.new (i32.const 0))
+     )
+    )
+   )
+   (unreachable)
+  )
+ )
+
  ;; CHECK:      (func $br_on_cast_unrelated (type $none_=>_ref?|$struct|) (result (ref null $struct))
  ;; CHECK-NEXT:  (local $nullable-struct2 (ref null $struct2))
  ;; CHECK-NEXT:  (block $block (result (ref null $struct))
diff --git a/test/lit/passes/remove-unused-brs_all-features.wast b/test/lit/passes/remove-unused-brs_all-features.wast
index 8ca6320..35d726a 100644
--- a/test/lit/passes/remove-unused-brs_all-features.wast
+++ b/test/lit/passes/remove-unused-brs_all-features.wast
@@ -8,8 +8,6 @@
  (type $vector (array (mut i32)))
  ;; CHECK:      (type $struct (struct (field (ref null $vector))))
  (type $struct (struct (field (ref null $vector))))
- ;; CHECK:      (type $ref|func|_=>_none (func (param (ref func))))
-
  ;; CHECK:      (type $i32_=>_none (func (param i32)))
 
  ;; CHECK:      (type $none_=>_ref?|$struct| (func (result (ref null $struct))))
@@ -22,7 +20,7 @@
 
  ;; CHECK:      (import "out" "log" (func $log (type $i32_=>_none) (param i32)))
  (import "out" "log" (func $log (param i32)))
- ;; CHECK:      (elem declare func $br_on-to-br $i32_=>_none $none_=>_i32)
+ ;; CHECK:      (elem declare func $i32_=>_none $none_=>_i32)
 
  ;; CHECK:      (func $foo (type $none_=>_ref?|$struct|) (result (ref null $struct))
  ;; CHECK-NEXT:  (if (result (ref null $struct))
@@ -115,111 +113,4 @@
    (ref.func $i32_=>_none)
   )
  )
-
- ;; CHECK:      (func $br_on-to-br (type $ref|func|_=>_none) (param $func (ref func))
- ;; CHECK-NEXT:  (call $log
- ;; CHECK-NEXT:   (i32.const 0)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (block $null
- ;; CHECK-NEXT:   (drop
- ;; CHECK-NEXT:    (ref.func $br_on-to-br)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:   (call $log
- ;; CHECK-NEXT:    (i32.const 1)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (call $log
- ;; CHECK-NEXT:   (i32.const 2)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (drop
- ;; CHECK-NEXT:   (block $func (result (ref $ref|func|_=>_none))
- ;; CHECK-NEXT:    (drop
- ;; CHECK-NEXT:     (br $func
- ;; CHECK-NEXT:      (ref.func $br_on-to-br)
- ;; CHECK-NEXT:     )
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (call $log
- ;; CHECK-NEXT:     (i32.const 3)
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (ref.func $br_on-to-br)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (call $log
- ;; CHECK-NEXT:   (i32.const 4)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (drop
- ;; CHECK-NEXT:   (block $i31 (result (ref i31))
- ;; CHECK-NEXT:    (drop
- ;; CHECK-NEXT:     (br $i31
- ;; CHECK-NEXT:      (i31.new
- ;; CHECK-NEXT:       (i32.const 42)
- ;; CHECK-NEXT:      )
- ;; CHECK-NEXT:     )
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (call $log
- ;; CHECK-NEXT:     (i32.const 5)
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (i31.new
- ;; CHECK-NEXT:     (i32.const 1337)
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (call $log
- ;; CHECK-NEXT:   (i32.const 6)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (drop
- ;; CHECK-NEXT:   (block $non-null (result (ref $ref|func|_=>_none))
- ;; CHECK-NEXT:    (br $non-null
- ;; CHECK-NEXT:     (ref.func $br_on-to-br)
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (call $log
- ;; CHECK-NEXT:     (i32.const 7)
- ;; CHECK-NEXT:    )
- ;; CHECK-NEXT:    (ref.func $br_on-to-br)
- ;; CHECK-NEXT:   )
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $br_on-to-br (param $func (ref func))
-  (call $log (i32.const 0))
-  (block $null
-   ;; a non-null reference is not null, and the br is never taken
-   (drop
-    (br_on_null $null (ref.func $br_on-to-br))
-   )
-   (call $log (i32.const 1))
-  )
-  (call $log (i32.const 2))
-  (drop
-   (block $func (result funcref)
-    ;; a non-null function reference means we always take the br
-    (drop
-     (br_on_func $func (ref.func $br_on-to-br))
-    )
-    (call $log (i32.const 3))
-    (ref.func $br_on-to-br)
-   )
-  )
-  (call $log (i32.const 4))
-  (drop
-   (block $i31 (result i31ref)
-    ;; a non-null i31 reference means we always take the br
-    (drop
-     (br_on_i31 $i31
-      (i31.new (i32.const 42))
-     )
-    )
-    (call $log (i32.const 5))
-    (i31.new (i32.const 1337))
-   )
-  )
-  (call $log (i32.const 6))
-  (drop
-   (block $non-null (result (ref func))
-    ;; a non-null reference is not null, and the br is always taken
-    (br_on_non_null $non-null (ref.func $br_on-to-br))
-    (call $log (i32.const 7))
-    (ref.func $br_on-to-br)
-   )
-  )
- )
 )
diff --git a/test/lit/passes/vacuum-gc.wast b/test/lit/passes/vacuum-gc.wast
index 69dbe0b..fcdeb8c 100644
--- a/test/lit/passes/vacuum-gc.wast
+++ b/test/lit/passes/vacuum-gc.wast
@@ -18,13 +18,13 @@
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT:  (drop
-  ;; CHECK-NEXT:   (ref.cast i31
+  ;; CHECK-NEXT:   (ref.cast null i31
   ;; CHECK-NEXT:    (local.get $x)
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
   (func $drop-ref-as (param $x anyref)
-    ;; Without -tnh, we must assume all ref_as* can have a trap effect, and so
+    ;; Without -tnh, we must assume all casts can have a trap effect, and so
     ;; we cannot remove anything here.
     (drop
       (ref.as_non_null
@@ -32,7 +32,7 @@
       )
     )
     (drop
-      (ref.as_i31
+      (ref.cast null i31
         (local.get $x)
       )
     )
diff --git a/test/lit/passes/vacuum-tnh.wast b/test/lit/passes/vacuum-tnh.wast
index f60c4c5..c3de8c2 100644
--- a/test/lit/passes/vacuum-tnh.wast
+++ b/test/lit/passes/vacuum-tnh.wast
@@ -33,7 +33,7 @@
   ;; NO_TNH-NEXT:   )
   ;; NO_TNH-NEXT:  )
   ;; NO_TNH-NEXT:  (drop
-  ;; NO_TNH-NEXT:   (ref.cast i31
+  ;; NO_TNH-NEXT:   (ref.cast null i31
   ;; NO_TNH-NEXT:    (local.get $y)
   ;; NO_TNH-NEXT:   )
   ;; NO_TNH-NEXT:  )
@@ -55,9 +55,9 @@
       )
     )
 
-    ;; Other ref.as* as well.
+    ;; Other casts as well.
     (drop
-      (ref.as_i31
+      (ref.cast null i31
         (local.get $y)
       )
     )
diff --git a/test/lit/ref-cast-nop.wast b/test/lit/ref-cast-nop.wast
deleted file mode 100644
index 3b284db..0000000
--- a/test/lit/ref-cast-nop.wast
+++ /dev/null
@@ -1,29 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
-
-;; RUN: wasm-opt -all %s -S --roundtrip -o - | filecheck %s
-
-(module
- ;; CHECK:      (type $struct (struct (field i32)))
- (type $struct (struct i32))
- ;; CHECK:      (func $ref.cast_nop (type $ref|any|_=>_ref|$struct|) (param $x (ref any)) (result (ref $struct))
- ;; CHECK-NEXT:  (ref.cast_nop $struct
- ;; CHECK-NEXT:   (local.get $x)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $ref.cast_nop (param $x (ref any)) (result (ref $struct))
-  (ref.cast_nop $struct
-   (local.get $x)
-  )
- )
-
- ;; CHECK:      (func $ref.cast_nop.null (type $ref|any|_=>_ref|none|) (param $x (ref any)) (result (ref none))
- ;; CHECK-NEXT:  (ref.cast_nop none
- ;; CHECK-NEXT:   (local.get $x)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT: )
- (func $ref.cast_nop.null (param $x (ref any)) (result (ref none))
-  (ref.cast_nop none
-   (local.get $x)
-  )
- )
-)
diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast
index 3155c38..b057e0c 100644
--- a/test/passes/Oz_fuzz-exec_all-features.wast
+++ b/test/passes/Oz_fuzz-exec_all-features.wast
@@ -179,7 +179,7 @@
  )
  (func "ref-as-func-of-func"
   (drop
-   (ref.as_func
+   (ref.cast func
     (ref.func $0)
    )
   )