@@ -219,13 +219,29 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
219
219
// Indicates no limit of maxDepth or maxLoopIterations.
220
220
static const Index NO_LIMIT = 0 ;
221
221
222
+ enum RelaxedBehavior {
223
+ // Consider relaxed SIMD instructions non-constant. This is suitable for
224
+ // optimizations, as we bake the results of optimizations into the output,
225
+ // but relaxed operations must behave according to the host semantics, not
226
+ // ours, so we do not want to optimize such expressions.
227
+ NonConstant,
228
+ // Execute relaxed SIMD instructions.
229
+ Execute,
230
+ };
231
+
232
+ protected:
233
+ RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant;
234
+
235
+ public:
222
236
ExpressionRunner (Module* module = nullptr ,
223
237
Index maxDepth = NO_LIMIT,
224
238
Index maxLoopIterations = NO_LIMIT)
225
239
: module(module), maxDepth(maxDepth), maxLoopIterations(maxLoopIterations) {
226
240
}
227
241
virtual ~ExpressionRunner () = default ;
228
242
243
+ void setRelaxedBehavior (RelaxedBehavior value) { relaxedBehavior = value; }
244
+
229
245
Flow visit (Expression* curr) {
230
246
depth++;
231
247
if (maxDepth != NO_LIMIT && depth > maxDepth) {
@@ -584,11 +600,21 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
584
600
return value.extAddPairwiseToSI32x4 ();
585
601
case ExtAddPairwiseUVecI16x8ToI32x4:
586
602
return value.extAddPairwiseToUI32x4 ();
587
- case TruncSatSVecF32x4ToVecI32x4:
588
603
case RelaxedTruncSVecF32x4ToVecI32x4:
604
+ // TODO: We could do this only if the actual values are in the relaxed
605
+ // range.
606
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
607
+ return NONCONSTANT_FLOW;
608
+ }
609
+ [[fallthrough]];
610
+ case TruncSatSVecF32x4ToVecI32x4:
589
611
return value.truncSatToSI32x4 ();
590
- case TruncSatUVecF32x4ToVecI32x4:
591
612
case RelaxedTruncUVecF32x4ToVecI32x4:
613
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
614
+ return NONCONSTANT_FLOW;
615
+ }
616
+ [[fallthrough]];
617
+ case TruncSatUVecF32x4ToVecI32x4:
592
618
return value.truncSatToUI32x4 ();
593
619
case ConvertSVecI32x4ToVecF32x4:
594
620
return value.convertSToF32x4 ();
@@ -622,11 +648,19 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
622
648
return value.convertLowSToF64x2 ();
623
649
case ConvertLowUVecI32x4ToVecF64x2:
624
650
return value.convertLowUToF64x2 ();
625
- case TruncSatZeroSVecF64x2ToVecI32x4:
626
651
case RelaxedTruncZeroSVecF64x2ToVecI32x4:
652
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
653
+ return NONCONSTANT_FLOW;
654
+ }
655
+ [[fallthrough]];
656
+ case TruncSatZeroSVecF64x2ToVecI32x4:
627
657
return value.truncSatZeroSToI32x4 ();
628
- case TruncSatZeroUVecF64x2ToVecI32x4:
629
658
case RelaxedTruncZeroUVecF64x2ToVecI32x4:
659
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
660
+ return NONCONSTANT_FLOW;
661
+ }
662
+ [[fallthrough]];
663
+ case TruncSatZeroUVecF64x2ToVecI32x4:
630
664
return value.truncSatZeroUToI32x4 ();
631
665
case DemoteZeroVecF64x2ToVecF32x4:
632
666
return value.demoteZeroToF32x4 ();
@@ -989,8 +1023,12 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
989
1023
return left.maxUI16x8 (right);
990
1024
case AvgrUVecI16x8:
991
1025
return left.avgrUI16x8 (right);
992
- case Q15MulrSatSVecI16x8:
993
1026
case RelaxedQ15MulrSVecI16x8:
1027
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1028
+ return NONCONSTANT_FLOW;
1029
+ }
1030
+ [[fallthrough]];
1031
+ case Q15MulrSatSVecI16x8:
994
1032
return left.q15MulrSatSI16x8 (right);
995
1033
case ExtMulLowSVecI16x8:
996
1034
return left.extMulLowSI16x8 (right);
@@ -1064,11 +1102,19 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
1064
1102
return left.mulF32x4 (right);
1065
1103
case DivVecF32x4:
1066
1104
return left.divF32x4 (right);
1067
- case MinVecF32x4:
1068
1105
case RelaxedMinVecF32x4:
1106
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1107
+ return NONCONSTANT_FLOW;
1108
+ }
1109
+ [[fallthrough]];
1110
+ case MinVecF32x4:
1069
1111
return left.minF32x4 (right);
1070
- case MaxVecF32x4:
1071
1112
case RelaxedMaxVecF32x4:
1113
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1114
+ return NONCONSTANT_FLOW;
1115
+ }
1116
+ [[fallthrough]];
1117
+ case MaxVecF32x4:
1072
1118
return left.maxF32x4 (right);
1073
1119
case PMinVecF32x4:
1074
1120
return left.pminF32x4 (right);
@@ -1082,11 +1128,19 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
1082
1128
return left.mulF64x2 (right);
1083
1129
case DivVecF64x2:
1084
1130
return left.divF64x2 (right);
1085
- case MinVecF64x2:
1086
1131
case RelaxedMinVecF64x2:
1132
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1133
+ return NONCONSTANT_FLOW;
1134
+ }
1135
+ [[fallthrough]];
1136
+ case MinVecF64x2:
1087
1137
return left.minF64x2 (right);
1088
- case MaxVecF64x2:
1089
1138
case RelaxedMaxVecF64x2:
1139
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1140
+ return NONCONSTANT_FLOW;
1141
+ }
1142
+ [[fallthrough]];
1143
+ case MaxVecF64x2:
1090
1144
return left.maxF64x2 (right);
1091
1145
case PMinVecF64x2:
1092
1146
return left.pminF64x2 (right);
@@ -1102,8 +1156,12 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
1102
1156
case NarrowUVecI32x4ToVecI16x8:
1103
1157
return left.narrowUToI16x8 (right);
1104
1158
1105
- case SwizzleVecI8x16:
1106
1159
case RelaxedSwizzleVecI8x16:
1160
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1161
+ return NONCONSTANT_FLOW;
1162
+ }
1163
+ [[fallthrough]];
1164
+ case SwizzleVecI8x16:
1107
1165
return left.swizzleI8x16 (right);
1108
1166
1109
1167
case DotI8x16I7x16SToVecI16x8:
@@ -1213,16 +1271,34 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
1213
1271
return c.bitselectV128 (a, b);
1214
1272
1215
1273
case RelaxedMaddVecF16x8:
1274
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1275
+ return NONCONSTANT_FLOW;
1276
+ }
1216
1277
return a.relaxedMaddF16x8 (b, c);
1217
1278
case RelaxedNmaddVecF16x8:
1279
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1280
+ return NONCONSTANT_FLOW;
1281
+ }
1218
1282
return a.relaxedNmaddF16x8 (b, c);
1219
1283
case RelaxedMaddVecF32x4:
1284
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1285
+ return NONCONSTANT_FLOW;
1286
+ }
1220
1287
return a.relaxedMaddF32x4 (b, c);
1221
1288
case RelaxedNmaddVecF32x4:
1289
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1290
+ return NONCONSTANT_FLOW;
1291
+ }
1222
1292
return a.relaxedNmaddF32x4 (b, c);
1223
1293
case RelaxedMaddVecF64x2:
1294
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1295
+ return NONCONSTANT_FLOW;
1296
+ }
1224
1297
return a.relaxedMaddF64x2 (b, c);
1225
1298
case RelaxedNmaddVecF64x2:
1299
+ if (relaxedBehavior == RelaxedBehavior::NonConstant) {
1300
+ return NONCONSTANT_FLOW;
1301
+ }
1226
1302
return a.relaxedNmaddF64x2 (b, c);
1227
1303
default :
1228
1304
// TODO: implement signselect and dot_add
0 commit comments