Bug 1079361: Use AsmJSSimdType rather than Type in SIMD type checking in asm.js; r=luke
authorBenjamin Bouvier <benj@benj.me>
Fri, 21 Nov 2014 12:14:06 +0100
changeset 241234 abe3335741bdaa2f45b439220d5d9858786ee0f8
parent 241233 973929d1f3144e3624025f912937cbe0c3a70f79
child 241235 38f5bfa0e2f7819f51518b5ca01e11fcf674c8be
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1079361
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1079361: Use AsmJSSimdType rather than Type in SIMD type checking in asm.js; r=luke
js/src/asmjs/AsmJSValidate.cpp
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -561,64 +561,39 @@ class Type
           case Float32x4:
             return MIRType_Float32x4;
           case Void:
             return MIRType_None;
         }
         MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid Type");
     }
 
-    Type simdToScalarType() const {
+    AsmJSSimdType simdType() const {
         MOZ_ASSERT(isSimd());
         switch (which_) {
           case Int32x4:
-            return Signed;
+            return AsmJSSimdType_int32x4;
           case Float32x4:
-            return Float;
+            return AsmJSSimdType_float32x4;
           // Scalar types
           case Double:
           case DoubleLit:
           case MaybeDouble:
           case Float:
           case MaybeFloat:
           case Floatish:
           case Fixnum:
           case Int:
           case Signed:
           case Unsigned:
           case Intish:
           case Void:
             break;
         }
-        MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type");
-    }
-
-    Type simdToCoercedScalarType() const {
-        MOZ_ASSERT(isSimd());
-        switch (which_) {
-          case Int32x4:
-            return Intish;
-          case Float32x4:
-            return Floatish;
-          // Scalar types
-          case Double:
-          case DoubleLit:
-          case MaybeDouble:
-          case Float:
-          case MaybeFloat:
-          case Floatish:
-          case Fixnum:
-          case Int:
-          case Signed:
-          case Unsigned:
-          case Intish:
-          case Void:
-            break;
-        }
-        MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type");
+        MOZ_CRASH("not a SIMD Type");
     }
 
     const char *toChars() const {
         switch (which_) {
           case Double:      return "double";
           case DoubleLit:   return "doublelit";
           case MaybeDouble: return "double?";
           case Float:       return "float";
@@ -4514,17 +4489,21 @@ CheckDotAccess(FunctionCompiler &f, Pars
         lane = LaneY;
     else if (field == names.z)
         lane = LaneZ;
     else if (field == names.w)
         lane = LaneW;
     else
         return f.fail(base, "dot access field must be a lane name (x, y, z, w) or signMask");
 
-    *type = baseType.simdToScalarType();
+    switch (baseType.simdType()) {
+      case AsmJSSimdType_int32x4:   *type = Type::Signed; break;
+      case AsmJSSimdType_float32x4: *type = Type::Float;  break;
+    }
+
     *def = f.extractSimdElement(lane, baseDef, type->toMIRType());
     return true;
 }
 
 static bool
 CheckStoreArray(FunctionCompiler &f, ParseNode *lhs, ParseNode *rhs, MDefinition **def, Type *type)
 {
     Scalar::Type viewType;
@@ -5366,65 +5345,77 @@ CheckSimdCallArgs(FunctionCompiler &f, P
     return true;
 }
 
 class CheckArgIsSubtypeOf
 {
     Type formalType_;
 
   public:
-    explicit CheckArgIsSubtypeOf(Type t) : formalType_(t) {}
+    explicit CheckArgIsSubtypeOf(AsmJSSimdType t) : formalType_(t) {}
 
     bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
                     MDefinition **def) const
     {
         if (!(actualType <= formalType_)) {
             return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
                            formalType_.toChars());
         }
         return true;
     }
 };
 
+static inline Type
+SimdToCoercedScalarType(AsmJSSimdType t)
+{
+    switch (t) {
+      case AsmJSSimdType_int32x4:
+        return Type::Intish;
+      case AsmJSSimdType_float32x4:
+        return Type::Floatish;
+    }
+    MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unexpected SIMD type");
+}
+
 class CheckSimdScalarArgs
 {
-    Type simdType_;
+    AsmJSSimdType simdType_;
     Type formalType_;
 
   public:
-    CheckSimdScalarArgs(Type simdType)
-      : simdType_(simdType), formalType_(simdType.simdToCoercedScalarType())
+    CheckSimdScalarArgs(AsmJSSimdType simdType)
+      : simdType_(simdType), formalType_(SimdToCoercedScalarType(simdType))
     {}
 
     bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
                     MDefinition **def) const
     {
         if (!(actualType <= formalType_)) {
             // As a special case, accept doublelit arguments to float32x4 ops by
             // re-emitting them as float32 constants.
-            if (!simdType_.isFloat32x4() || !actualType.isDoubleLit()) {
+            if (simdType_ != AsmJSSimdType_float32x4 || !actualType.isDoubleLit()) {
                 return f.failf(arg, "%s is not a subtype of %s%s",
                                actualType.toChars(), formalType_.toChars(),
-                               simdType_.isFloat32x4() ? " or doublelit" : "");
+                               simdType_ == AsmJSSimdType_float32x4 ? " or doublelit" : "");
             }
 
             AsmJSNumLit doubleLit = ExtractNumericLiteral(f.m(), arg);
             MOZ_ASSERT(doubleLit.which() == AsmJSNumLit::Double);
             *def = f.constant(doubleLit.scalarValue(), Type::Float);
         }
         return true;
     }
 };
 
 class CheckSimdSelectArgs
 {
     Type formalType_;
 
   public:
-    explicit CheckSimdSelectArgs(Type t) : formalType_(t) {}
+    explicit CheckSimdSelectArgs(AsmJSSimdType t) : formalType_(t) {}
 
     bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
                     MDefinition **def) const
     {
         if (argIndex == 0) {
             // First argument of select is an int32x4 mask.
             if (!(actualType <= Type::Int32x4))
                 return f.failf(arg, "%s is not a subtype of Int32x4", actualType.toChars());
@@ -5436,144 +5427,151 @@ class CheckSimdSelectArgs
                            formalType_.toChars());
         }
         return true;
     }
 };
 
 class CheckSimdVectorScalarArgs
 {
-    Type formalType_;
+    AsmJSSimdType formalSimdType_;
 
   public:
-    explicit CheckSimdVectorScalarArgs(Type t) : formalType_(t) {}
+    explicit CheckSimdVectorScalarArgs(AsmJSSimdType t) : formalSimdType_(t) {}
 
     bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
                     MDefinition **def) const
     {
         MOZ_ASSERT(argIndex < 2);
         if (argIndex == 0) {
             // First argument is the vector
-            if (!(actualType <= formalType_)) {
+            if (!(actualType <= Type(formalSimdType_))) {
                 return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
-                               formalType_.toChars());
+                               Type(formalSimdType_).toChars());
             }
             return true;
         }
 
         // Second argument is the scalar
-        Type coercedFormalType = formalType_.simdToCoercedScalarType();
+        Type coercedFormalType = SimdToCoercedScalarType(formalSimdType_);
         if (!(actualType <= coercedFormalType)) {
             return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
                            coercedFormalType.toChars());
         }
         return true;
     }
 };
 
 } // anonymous namespace
 
 static inline bool
-CheckSimdUnary(FunctionCompiler &f, ParseNode *call, Type retType, MSimdUnaryArith::Operation op,
-               MDefinition **def, Type *type)
+CheckSimdUnary(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType,
+               MSimdUnaryArith::Operation op, MDefinition **def, Type *type)
 {
     DefinitionVector defs;
-    if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(retType), &defs))
-        return false;
-    *def = f.unarySimd(defs[0], op, retType.toMIRType());
-    *type = retType;
+    if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType), &defs))
+        return false;
+    *type = opType;
+    *def = f.unarySimd(defs[0], op, type->toMIRType());
     return true;
 }
 
 template<class OpEnum>
 static inline bool
-CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, MDefinition **def,
-                Type *type)
+CheckSimdBinary(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, OpEnum op,
+                MDefinition **def, Type *type)
 {
     DefinitionVector argDefs;
-    if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs))
-        return false;
-    *def = f.binarySimd(argDefs[0], argDefs[1], op, retType.toMIRType());
-    *type = retType;
+    if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType), &argDefs))
+        return false;
+    *type = opType;
+    *def = f.binarySimd(argDefs[0], argDefs[1], op, type->toMIRType());
+    return true;
+}
+
+template<>
+inline bool
+CheckSimdBinary<MSimdBinaryComp::Operation>(FunctionCompiler &f, ParseNode *call,
+                                            AsmJSSimdType opType, MSimdBinaryComp::Operation op,
+                                            MDefinition **def, Type *type)
+{
+    DefinitionVector argDefs;
+    if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType), &argDefs))
+        return false;
+    *type = Type::Int32x4;
+    *def = f.binarySimd<MSimdBinaryComp>(argDefs[0], argDefs[1], op);
     return true;
 }
 
 template<>
 inline bool
-CheckSimdBinary<MSimdBinaryComp::Operation>(FunctionCompiler &f, ParseNode *call, Type retType,
-                                            MSimdBinaryComp::Operation op, MDefinition **def,
-                                            Type *type)
-{
-    DefinitionVector argDefs;
-    if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs))
-        return false;
-    *def = f.binarySimd<MSimdBinaryComp>(argDefs[0], argDefs[1], op);
-    *type = Type::Int32x4;
-    return true;
-}
-
-template<>
-inline bool
-CheckSimdBinary<MSimdShift::Operation>(FunctionCompiler &f, ParseNode *call, Type retType,
+CheckSimdBinary<MSimdShift::Operation>(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType,
                                        MSimdShift::Operation op, MDefinition **def, Type *type)
 {
     DefinitionVector argDefs;
-    if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(retType), &argDefs))
-        return false;
+    if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(opType), &argDefs))
+        return false;
+    *type = Type::Int32x4;
     *def = f.binarySimd<MSimdShift>(argDefs[0], argDefs[1], op);
-    *type = Type::Int32x4;
     return true;
 }
 
 static bool
-CheckSimdWith(FunctionCompiler &f, ParseNode *call, Type retType, SimdLane lane, MDefinition **def,
-              Type *type)
+CheckSimdWith(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, SimdLane lane,
+              MDefinition **def, Type *type)
 {
     DefinitionVector defs;
-    if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(retType), &defs))
-        return false;
-    *def = f.insertElementSimd(defs[0], defs[1], lane, retType.toMIRType());
-    *type = retType;
+    if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(opType), &defs))
+        return false;
+    *type = opType;
+    *def = f.insertElementSimd(defs[0], defs[1], lane, type->toMIRType());
     return true;
 }
 
+namespace {
+// Include CheckSimdCast in unnamed namespace to avoid MSVC name lookup bug (due to the use of Type).
+
 template<class T>
 static bool
-CheckSimdCast(FunctionCompiler &f, ParseNode *call, Type fromType, Type toType, MDefinition **def,
-              Type *type)
+CheckSimdCast(FunctionCompiler &f, ParseNode *call, AsmJSSimdType fromType, AsmJSSimdType toType,
+              MDefinition **def, Type *type)
 {
     DefinitionVector defs;
     if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(fromType), &defs))
         return false;
-    *def = f.convertSimd<T>(defs[0], fromType.toMIRType(), toType.toMIRType());
     *type = toType;
+    *def = f.convertSimd<T>(defs[0], Type(fromType).toMIRType(), type->toMIRType());
     return true;
 }
 
+}
+
 static bool
 CheckSimdShuffleSelectors(FunctionCompiler &f, ParseNode *lane, int32_t lanes[4], uint32_t maxLane)
 {
     for (unsigned i = 0; i < 4; i++, lane = NextNode(lane)) {
         uint32_t u32;
         if (!IsLiteralInt(f.m(), lane, &u32))
             return f.failf(lane, "lane selector should be a constant integer literal");
         if (u32 >= maxLane)
             return f.failf(lane, "lane selector should be less than %u", maxLane);
         lanes[i] = int32_t(u32);
     }
     return true;
 }
 
 static bool
-CheckSimdSwizzle(FunctionCompiler &f, ParseNode *call, Type retType, MDefinition **def, Type *type)
+CheckSimdSwizzle(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefinition **def,
+                 Type *type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 5)
         return f.failf(call, "expected 5 arguments to SIMD swizzle, got %u", numArgs);
 
+    Type retType = opType;
     ParseNode *vec = CallArgList(call);
     MDefinition *vecDef;
     Type vecType;
     if (!CheckExpr(f, vec, &vecDef, &vecType))
         return false;
     if (!(vecType <= retType))
         return f.failf(vec, "%s is not a subtype of %s", vecType.toChars(), retType.toChars());
 
@@ -5582,22 +5580,24 @@ CheckSimdSwizzle(FunctionCompiler &f, Pa
         return false;
 
     *def = f.swizzleSimd(vecDef, lanes[0], lanes[1], lanes[2], lanes[3], retType.toMIRType());
     *type = retType;
     return true;
 }
 
 static bool
-CheckSimdShuffle(FunctionCompiler &f, ParseNode *call, Type retType, MDefinition **def, Type *type)
+CheckSimdShuffle(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefinition **def,
+                 Type *type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 6)
         return f.failf(call, "expected 6 arguments to SIMD shuffle, got %u", numArgs);
 
+    Type retType = opType;
     ParseNode *arg = CallArgList(call);
     MDefinition *vecs[2];
     for (unsigned i = 0; i < 2; i++, arg = NextNode(arg)) {
         Type type;
         if (!CheckExpr(f, arg, &vecs[i], &type))
             return false;
         if (!(type <= retType))
             return f.failf(arg, "%s is not a subtype of %s", type.toChars(), retType.toChars());
@@ -5609,42 +5609,39 @@ CheckSimdShuffle(FunctionCompiler &f, Pa
 
     *def = f.shuffleSimd(vecs[0], vecs[1], lanes[0], lanes[1], lanes[2], lanes[3],
                          retType.toMIRType());
     *type = retType;
     return true;
 }
 
 static bool
-CheckSimdLoadStoreArgs(FunctionCompiler &f, ParseNode *call, Type retType,
+CheckSimdLoadStoreArgs(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType,
                        AsmJSHeapAccess::ViewType *viewType, MDefinition **index,
                        NeedsBoundsCheck *needsBoundsCheck)
 {
-    MOZ_ASSERT(retType.isSimd());
-    if (retType.isInt32x4())
-        *viewType = AsmJSHeapAccess::Int32x4;
-    else if (retType.isFloat32x4())
-        *viewType = AsmJSHeapAccess::Float32x4;
-    else
-        MOZ_CRASH("unexpected SIMD type");
-
     ParseNode *view = CallArgList(call);
     if (!view->isKind(PNK_NAME))
         return f.fail(view, "expected Uint8Array view as SIMD.*.store first argument");
 
     const ModuleCompiler::Global *global = f.lookupGlobal(view->name());
     if (!global ||
         global->which() != ModuleCompiler::Global::ArrayView ||
         global->viewType() != Scalar::Uint8)
     {
         return f.fail(view, "expected Uint8Array view as SIMD.*.store first argument");
     }
 
     *needsBoundsCheck = NEEDS_BOUNDS_CHECK;
 
+    switch (opType) {
+      case AsmJSSimdType_int32x4:   *viewType = AsmJSHeapAccess::Int32x4;   break;
+      case AsmJSSimdType_float32x4: *viewType = AsmJSHeapAccess::Float32x4; break;
+    }
+
     ParseNode *indexExpr = NextNode(view);
     uint32_t indexLit;
     if (IsLiteralOrConstInt(f, indexExpr, &indexLit)) {
         if (indexLit > INT32_MAX)
             return f.fail(indexExpr, "constant index out of range");
 
         if (!f.m().tryRequireHeapLengthToBeAtLeast(indexLit + Simd128DataSize)) {
             return f.failf(indexExpr, "constant index outside heap size range declared by the "
@@ -5666,46 +5663,47 @@ CheckSimdLoadStoreArgs(FunctionCompiler 
         return f.failf(indexExpr, "%s is not a subtype of intish", indexType.toChars());
 
     f.leaveHeapExpression();
 
     return true;
 }
 
 static bool
-CheckSimdLoad(FunctionCompiler &f, ParseNode *call, Type retType, MDefinition **def, Type *type)
+CheckSimdLoad(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefinition **def, Type *type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 2)
         return f.failf(call, "expected 2 arguments to SIMD load, got %u", numArgs);
 
     AsmJSHeapAccess::ViewType viewType;
     MDefinition *index;
     NeedsBoundsCheck needsBoundsCheck;
-    if (!CheckSimdLoadStoreArgs(f, call, retType, &viewType, &index, &needsBoundsCheck))
+    if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &index, &needsBoundsCheck))
         return false;
 
     *def = f.loadHeap(viewType, index, needsBoundsCheck);
-    *type = retType;
+    *type = opType;
     return true;
 }
 
 static bool
-CheckSimdStore(FunctionCompiler &f, ParseNode *call, Type retType, MDefinition **def, Type *type)
+CheckSimdStore(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefinition **def, Type *type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 3)
         return f.failf(call, "expected 3 arguments to SIMD load, got %u", numArgs);
 
     AsmJSHeapAccess::ViewType viewType;
     MDefinition *index;
     NeedsBoundsCheck needsBoundsCheck;
-    if (!CheckSimdLoadStoreArgs(f, call, retType, &viewType, &index, &needsBoundsCheck))
-        return false;
-
+    if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &index, &needsBoundsCheck))
+        return false;
+
+    Type retType = opType;
     ParseNode *vecExpr = NextNode(NextNode(CallArgList(call)));
     MDefinition *vec;
     Type vecType;
     if (!CheckExpr(f, vecExpr, &vec, &vecType))
         return false;
     if (!(vecType <= retType))
         return f.failf(vecExpr, "%s is not a subtype of %s", vecType.toChars(), retType.toChars());
 
@@ -5716,116 +5714,116 @@ CheckSimdStore(FunctionCompiler &f, Pars
 }
 
 static bool
 CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
                        MDefinition **def, Type *type)
 {
     MOZ_ASSERT(global->isSimdOperation());
 
-    Type retType = global->simdOperationType();
+    AsmJSSimdType opType = global->simdOperationType();
 
     switch (global->simdOperation()) {
       case AsmJSSimdOperation_add:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Add, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Add, def, type);
       case AsmJSSimdOperation_sub:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Sub, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Sub, def, type);
       case AsmJSSimdOperation_mul:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Mul, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Mul, def, type);
       case AsmJSSimdOperation_div:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Div, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Div, def, type);
       case AsmJSSimdOperation_max:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Max, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Max, def, type);
       case AsmJSSimdOperation_min:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Min, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Min, def, type);
 
       case AsmJSSimdOperation_lessThan:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThan, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThan, def, type);
       case AsmJSSimdOperation_lessThanOrEqual:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThanOrEqual, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThanOrEqual, def, type);
       case AsmJSSimdOperation_equal:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::equal, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::equal, def, type);
       case AsmJSSimdOperation_notEqual:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::notEqual, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::notEqual, def, type);
       case AsmJSSimdOperation_greaterThan:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThan, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::greaterThan, def, type);
       case AsmJSSimdOperation_greaterThanOrEqual:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThanOrEqual, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryComp::greaterThanOrEqual, def, type);
 
       case AsmJSSimdOperation_and:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::and_, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::and_, def, type);
       case AsmJSSimdOperation_or:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::or_, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::or_, def, type);
       case AsmJSSimdOperation_xor:
-        return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::xor_, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::xor_, def, type);
 
       case AsmJSSimdOperation_withX:
-        return CheckSimdWith(f, call, retType, SimdLane::LaneX, def, type);
+        return CheckSimdWith(f, call, opType, SimdLane::LaneX, def, type);
       case AsmJSSimdOperation_withY:
-        return CheckSimdWith(f, call, retType, SimdLane::LaneY, def, type);
+        return CheckSimdWith(f, call, opType, SimdLane::LaneY, def, type);
       case AsmJSSimdOperation_withZ:
-        return CheckSimdWith(f, call, retType, SimdLane::LaneZ, def, type);
+        return CheckSimdWith(f, call, opType, SimdLane::LaneZ, def, type);
       case AsmJSSimdOperation_withW:
-        return CheckSimdWith(f, call, retType, SimdLane::LaneW, def, type);
+        return CheckSimdWith(f, call, opType, SimdLane::LaneW, def, type);
 
       case AsmJSSimdOperation_fromInt32x4:
-        return CheckSimdCast<MSimdConvert>(f, call, Type::Int32x4, retType, def, type);
+        return CheckSimdCast<MSimdConvert>(f, call, AsmJSSimdType_int32x4, opType, def, type);
       case AsmJSSimdOperation_fromInt32x4Bits:
-        return CheckSimdCast<MSimdReinterpretCast>(f, call, Type::Int32x4, retType, def, type);
+        return CheckSimdCast<MSimdReinterpretCast>(f, call, AsmJSSimdType_int32x4, opType, def, type);
       case AsmJSSimdOperation_fromFloat32x4:
-        return CheckSimdCast<MSimdConvert>(f, call, Type::Float32x4, retType, def, type);
+        return CheckSimdCast<MSimdConvert>(f, call, AsmJSSimdType_float32x4, opType, def, type);
       case AsmJSSimdOperation_fromFloat32x4Bits:
-        return CheckSimdCast<MSimdReinterpretCast>(f, call, Type::Float32x4, retType, def, type);
+        return CheckSimdCast<MSimdReinterpretCast>(f, call, AsmJSSimdType_float32x4, opType, def, type);
 
       case AsmJSSimdOperation_shiftLeft:
-        return CheckSimdBinary(f, call, Type::Int32x4, MSimdShift::lsh, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdShift::lsh, def, type);
       case AsmJSSimdOperation_shiftRight:
-        return CheckSimdBinary(f, call, Type::Int32x4, MSimdShift::rsh, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdShift::rsh, def, type);
       case AsmJSSimdOperation_shiftRightLogical:
-        return CheckSimdBinary(f, call, Type::Int32x4, MSimdShift::ursh, def, type);
+        return CheckSimdBinary(f, call, opType, MSimdShift::ursh, def, type);
 
       case AsmJSSimdOperation_abs:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::abs, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::abs, def, type);
       case AsmJSSimdOperation_neg:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::neg, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::neg, def, type);
       case AsmJSSimdOperation_not:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::not_, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::not_, def, type);
       case AsmJSSimdOperation_sqrt:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::sqrt, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::sqrt, def, type);
       case AsmJSSimdOperation_reciprocal:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::reciprocal, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::reciprocal, def, type);
       case AsmJSSimdOperation_reciprocalSqrt:
-        return CheckSimdUnary(f, call, retType, MSimdUnaryArith::reciprocalSqrt, def, type);
+        return CheckSimdUnary(f, call, opType, MSimdUnaryArith::reciprocalSqrt, def, type);
 
       case AsmJSSimdOperation_swizzle:
-        return CheckSimdSwizzle(f, call, retType, def, type);
+        return CheckSimdSwizzle(f, call, opType, def, type);
       case AsmJSSimdOperation_shuffle:
-        return CheckSimdShuffle(f, call, retType, def, type);
+        return CheckSimdShuffle(f, call, opType, def, type);
 
       case AsmJSSimdOperation_load:
-        return CheckSimdLoad(f, call, retType, def, type);
+        return CheckSimdLoad(f, call, opType, def, type);
       case AsmJSSimdOperation_store:
-        return CheckSimdStore(f, call, retType, def, type);
+        return CheckSimdStore(f, call, opType, def, type);
 
       case AsmJSSimdOperation_splat: {
         DefinitionVector defs;
-        if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(retType), &defs))
-            return false;
-        *def = f.splatSimd(defs[0], retType.toMIRType());
-        *type = retType;
+        if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(opType), &defs))
+            return false;
+        *type = opType;
+        *def = f.splatSimd(defs[0], type->toMIRType());
         return true;
       }
 
       case AsmJSSimdOperation_select: {
         DefinitionVector defs;
-        if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(retType), &defs))
-            return false;
+        if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(opType), &defs))
+            return false;
+        *type = opType;
         *def = f.ternarySimd(defs[0], defs[1], defs[2], MSimdTernaryBitwise::select,
-                             retType.toMIRType());
-        *type = retType;
+                             type->toMIRType());
         return true;
       }
     }
     MOZ_CRASH("unexpected simd operation in CheckSimdOperationCall");
 }
 
 static bool
 CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
@@ -5834,26 +5832,25 @@ CheckSimdCtorCall(FunctionCompiler &f, P
     MOZ_ASSERT(call->isKind(PNK_CALL));
 
     AsmJSCoercion coercion;
     ParseNode *argNode;
     if (IsCoercionCall(f.m(), call, &coercion, &argNode))
         return CheckCoercionArg(f, argNode, coercion, def, type);
 
     AsmJSSimdType simdType = global->simdCtorType();
-    Type retType = simdType;
     unsigned length = SimdTypeToLength(simdType);
     DefinitionVector defs;
-    if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(retType), &defs))
+    if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(simdType), &defs))
         return false;
 
     // This code will need to be generalized when we handle float64x2
     MOZ_ASSERT(length == 4);
-    *def = f.constructSimd<MSimdValueX4>(defs[0], defs[1], defs[2], defs[3], retType.toMIRType());
-    *type = retType;
+    *type = simdType;
+    *def = f.constructSimd<MSimdValueX4>(defs[0], defs[1], defs[2], defs[3], type->toMIRType());
     return true;
 }
 
 static bool
 CheckUncoercedCall(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type)
 {
     MOZ_ASSERT(expr->isKind(PNK_CALL));