|
1038 | 1038 |
|
1039 | 1039 | ;; YESTNH: (type $2 (func (result (ref none)))) |
1040 | 1040 |
|
| 1041 | + ;; YESTNH: (type $3 (func (param (ref $A)) (result (ref none)))) |
| 1042 | + |
1041 | 1043 | ;; YESTNH: (func $test (type $2) (result (ref none)) |
1042 | 1044 | ;; YESTNH-NEXT: (drop |
1043 | 1045 | ;; YESTNH-NEXT: (struct.new_default $A |
|
1048 | 1050 | ;; YESTNH-NEXT: ) |
1049 | 1051 | ;; NO_TNH: (type $2 (func (result (ref none)))) |
1050 | 1052 |
|
| 1053 | + ;; NO_TNH: (type $3 (func (param (ref $A)) (result (ref none)))) |
| 1054 | + |
1051 | 1055 | ;; NO_TNH: (func $test (type $2) (result (ref none)) |
1052 | 1056 | ;; NO_TNH-NEXT: (drop |
1053 | 1057 | ;; NO_TNH-NEXT: (struct.new_default $A |
|
1063 | 1067 | ) |
1064 | 1068 | ) |
1065 | 1069 | ) |
| 1070 | + |
| 1071 | + ;; YESTNH: (func $inexact (type $3) (param $inexact (ref $A)) (result (ref none)) |
| 1072 | + ;; YESTNH-NEXT: (drop |
| 1073 | + ;; YESTNH-NEXT: (local.get $inexact) |
| 1074 | + ;; YESTNH-NEXT: ) |
| 1075 | + ;; YESTNH-NEXT: (unreachable) |
| 1076 | + ;; YESTNH-NEXT: ) |
| 1077 | + ;; NO_TNH: (func $inexact (type $3) (param $inexact (ref $A)) (result (ref none)) |
| 1078 | + ;; NO_TNH-NEXT: (drop |
| 1079 | + ;; NO_TNH-NEXT: (local.get $inexact) |
| 1080 | + ;; NO_TNH-NEXT: ) |
| 1081 | + ;; NO_TNH-NEXT: (unreachable) |
| 1082 | + ;; NO_TNH-NEXT: ) |
| 1083 | + (func $inexact (param $inexact (ref $A)) (result (ref $B)) |
| 1084 | + ;; As above, but now the input type is inexact. There are no subtypes, so |
| 1085 | + ;; we still optimize. |
| 1086 | + (ref.get_desc $A |
| 1087 | + (local.get $inexact) |
| 1088 | + ) |
| 1089 | + ) |
| 1090 | +) |
| 1091 | + |
| 1092 | +(module |
| 1093 | + ;; As above, but now there are subtypes $A.sub, $B.sub. |
| 1094 | + (rec |
| 1095 | + ;; YESTNH: (rec |
| 1096 | + ;; YESTNH-NEXT: (type $A (sub (descriptor $B (struct)))) |
| 1097 | + ;; NO_TNH: (rec |
| 1098 | + ;; NO_TNH-NEXT: (type $A (sub (descriptor $B (struct)))) |
| 1099 | + (type $A (sub (descriptor $B (struct)))) |
| 1100 | + ;; YESTNH: (type $B (sub (describes $A (struct)))) |
| 1101 | + ;; NO_TNH: (type $B (sub (describes $A (struct)))) |
| 1102 | + (type $B (sub (describes $A (struct)))) |
| 1103 | + |
| 1104 | + ;; YESTNH: (type $A.sub (sub $A (descriptor $B.sub (struct)))) |
| 1105 | + ;; NO_TNH: (type $A.sub (sub $A (descriptor $B.sub (struct)))) |
| 1106 | + (type $A.sub (sub $A (descriptor $B.sub (struct)))) |
| 1107 | + ;; YESTNH: (type $B.sub (sub $B (describes $A.sub (struct)))) |
| 1108 | + ;; NO_TNH: (type $B.sub (sub $B (describes $A.sub (struct)))) |
| 1109 | + (type $B.sub (sub $B (describes $A.sub (struct)))) |
| 1110 | + ) |
| 1111 | + |
| 1112 | + ;; YESTNH: (type $4 (func)) |
| 1113 | + |
| 1114 | + ;; YESTNH: (type $5 (func (result (ref (exact $B.sub))))) |
| 1115 | + |
| 1116 | + ;; YESTNH: (type $6 (func (param (ref $A)) (result (ref $B.sub)))) |
| 1117 | + |
| 1118 | + ;; YESTNH: (func $create (type $4) |
| 1119 | + ;; YESTNH-NEXT: (drop |
| 1120 | + ;; YESTNH-NEXT: (struct.new_default $A.sub |
| 1121 | + ;; YESTNH-NEXT: (struct.new_default $B.sub) |
| 1122 | + ;; YESTNH-NEXT: ) |
| 1123 | + ;; YESTNH-NEXT: ) |
| 1124 | + ;; YESTNH-NEXT: ) |
| 1125 | + ;; NO_TNH: (type $4 (func)) |
| 1126 | + |
| 1127 | + ;; NO_TNH: (type $5 (func (result (ref (exact $B))))) |
| 1128 | + |
| 1129 | + ;; NO_TNH: (type $6 (func (param (ref $A)) (result (ref $B)))) |
| 1130 | + |
| 1131 | + ;; NO_TNH: (func $create (type $4) |
| 1132 | + ;; NO_TNH-NEXT: (drop |
| 1133 | + ;; NO_TNH-NEXT: (struct.new_default $A.sub |
| 1134 | + ;; NO_TNH-NEXT: (struct.new_default $B.sub) |
| 1135 | + ;; NO_TNH-NEXT: ) |
| 1136 | + ;; NO_TNH-NEXT: ) |
| 1137 | + ;; NO_TNH-NEXT: ) |
| 1138 | + (func $create |
| 1139 | + ;; Make the subtypes not abstract. |
| 1140 | + (drop |
| 1141 | + (struct.new_default $A.sub |
| 1142 | + (struct.new_default $B.sub) |
| 1143 | + ) |
| 1144 | + ) |
| 1145 | + ) |
| 1146 | + |
| 1147 | + ;; YESTNH: (func $test (type $5) (result (ref (exact $B.sub))) |
| 1148 | + ;; YESTNH-NEXT: (drop |
| 1149 | + ;; YESTNH-NEXT: (struct.new_default $A |
| 1150 | + ;; YESTNH-NEXT: (ref.null none) |
| 1151 | + ;; YESTNH-NEXT: ) |
| 1152 | + ;; YESTNH-NEXT: ) |
| 1153 | + ;; YESTNH-NEXT: (unreachable) |
| 1154 | + ;; YESTNH-NEXT: ) |
| 1155 | + ;; NO_TNH: (func $test (type $5) (result (ref (exact $B))) |
| 1156 | + ;; NO_TNH-NEXT: (ref.get_desc $A |
| 1157 | + ;; NO_TNH-NEXT: (struct.new_default $A |
| 1158 | + ;; NO_TNH-NEXT: (ref.null none) |
| 1159 | + ;; NO_TNH-NEXT: ) |
| 1160 | + ;; NO_TNH-NEXT: ) |
| 1161 | + ;; NO_TNH-NEXT: ) |
| 1162 | + (func $test (result (ref (exact $B))) |
| 1163 | + ;; We can still optimize here, thanks to exactness (when TNH). |
| 1164 | + (ref.get_desc $A |
| 1165 | + (struct.new_default $A |
| 1166 | + (ref.null none) |
| 1167 | + ) |
| 1168 | + ) |
| 1169 | + ) |
| 1170 | + |
| 1171 | + ;; YESTNH: (func $inexact (type $6) (param $inexact (ref $A)) (result (ref $B.sub)) |
| 1172 | + ;; YESTNH-NEXT: (ref.get_desc $A.sub |
| 1173 | + ;; YESTNH-NEXT: (ref.cast (ref $A.sub) |
| 1174 | + ;; YESTNH-NEXT: (local.get $inexact) |
| 1175 | + ;; YESTNH-NEXT: ) |
| 1176 | + ;; YESTNH-NEXT: ) |
| 1177 | + ;; YESTNH-NEXT: ) |
| 1178 | + ;; NO_TNH: (func $inexact (type $6) (param $inexact (ref $A)) (result (ref $B)) |
| 1179 | + ;; NO_TNH-NEXT: (ref.get_desc $A |
| 1180 | + ;; NO_TNH-NEXT: (local.get $inexact) |
| 1181 | + ;; NO_TNH-NEXT: ) |
| 1182 | + ;; NO_TNH-NEXT: ) |
| 1183 | + (func $inexact (param $inexact (ref $A)) (result (ref $B)) |
| 1184 | + ;; We do not optimize to an unreachable here, as the inexact reference may |
| 1185 | + ;; contain an $A.sub. We optimize to that, using a cast (in TNH). |
| 1186 | + (ref.get_desc $A |
| 1187 | + (local.get $inexact) |
| 1188 | + ) |
| 1189 | + ) |
1066 | 1190 | ) |
1067 | 1191 |
|
0 commit comments