Updating the x86 HWIntrinsics to query flags via explicit methods.
authorTanner Gooding <tagoo@outlook.com>
Sat, 2 Jun 2018 18:19:57 +0000 (11:19 -0700)
committerTanner Gooding <tagoo@outlook.com>
Sat, 2 Jun 2018 21:23:38 +0000 (14:23 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/05b05fa9e4ee44fcf5b8246fbbafc9b16b519abb

src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/gentree.cpp
src/coreclr/src/jit/hwintrinsiccodegenxarch.cpp
src/coreclr/src/jit/hwintrinsicxarch.cpp
src/coreclr/src/jit/hwintrinsicxarch.h
src/coreclr/src/jit/lowerxarch.cpp
src/coreclr/src/jit/lsraxarch.cpp

index a7a6e71d739ce496092bc2f004746cdf6fb143ed..e8c45945fed867e63cc5783e6947d76942c248c7 100644 (file)
@@ -3015,7 +3015,7 @@ protected:
     GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass);
     GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType);
     GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand);
-    bool hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags);
+    bool hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, NamedIntrinsic intrinsic);
 #endif // _TARGET_XARCH_
 #ifdef _TARGET_ARM64_
     InstructionSet lookupHWIntrinsicISA(const char* className);
index b40c026367a2eac814fc93ee42f3f91ed0512572..47d76e1a760c2ba76479aed91c272129d4a46941 100644 (file)
@@ -17384,8 +17384,7 @@ bool GenTree::isCommutativeHWIntrinsic() const
     assert(gtOper == GT_HWIntrinsic);
 
 #ifdef _TARGET_XARCH_
-    HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(AsHWIntrinsic()->gtHWIntrinsicId);
-    return ((flags & HW_Flag_Commutative) != 0);
+    return HWIntrinsicInfo::IsCommutative(AsHWIntrinsic()->gtHWIntrinsicId);
 #else
     return false;
 #endif // _TARGET_XARCH_
@@ -17428,8 +17427,7 @@ bool GenTree::isRMWHWIntrinsic(Compiler* comp)
 #ifdef _TARGET_XARCH_
     if (!comp->canUseVexEncoding())
     {
-        HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(AsHWIntrinsic()->gtHWIntrinsicId);
-        return ((flags & HW_Flag_NoRMWSemantics) == 0);
+        return HWIntrinsicInfo::HasRMWSemantics(AsHWIntrinsic()->gtHWIntrinsicId);
     }
 
     switch (AsHWIntrinsic()->gtHWIntrinsicId)
@@ -17447,10 +17445,14 @@ bool GenTree::isRMWHWIntrinsic(Compiler* comp)
         case NI_FMA_MultiplySubtractNegated:
         case NI_FMA_MultiplySubtractNegatedScalar:
         case NI_FMA_MultiplySubtractScalar:
+        {
             return true;
+        }
 
         default:
+        {
             return false;
+        }
     }
 #else
     return false;
index f21088962039034916341f1c20733a5e34975913..c7decfa2f0f0759f01701f2fbb1e49a5cc09d860 100644 (file)
@@ -33,13 +33,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 // Return Value:
 //    returns true if this category can be table-driven in CodeGen
 //
-static bool genIsTableDrivenHWIntrinsic(HWIntrinsicCategory category, HWIntrinsicFlag flags)
+static bool genIsTableDrivenHWIntrinsic(NamedIntrinsic intrinsicId, HWIntrinsicCategory category)
 {
     // TODO - make more categories to the table-driven framework
     // HW_Category_Helper and HW_Flag_MultiIns/HW_Flag_SpecialCodeGen usually need manual codegen
     const bool tableDrivenCategory =
-        category != HW_Category_Special && category != HW_Category_Scalar && category != HW_Category_Helper;
-    const bool tableDrivenFlag = (flags & (HW_Flag_MultiIns | HW_Flag_SpecialCodeGen)) == 0;
+        (category != HW_Category_Special) && (category != HW_Category_Scalar) && (category != HW_Category_Helper);
+    const bool tableDrivenFlag = !(HWIntrinsicInfo::GeneratesMultipleIns(intrinsicId) | HWIntrinsicInfo::HasSpecialCodegen(intrinsicId));
     return tableDrivenCategory && tableDrivenFlag;
 }
 
@@ -54,13 +54,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
     NamedIntrinsic      intrinsicId = node->gtHWIntrinsicId;
     InstructionSet      isa         = HWIntrinsicInfo::lookupIsa(intrinsicId);
     HWIntrinsicCategory category    = HWIntrinsicInfo::lookupCategory(intrinsicId);
-    HWIntrinsicFlag     flags       = HWIntrinsicInfo::lookupFlags(intrinsicId);
     int                 ival        = HWIntrinsicInfo::lookupIval(intrinsicId);
     int                 numArgs     = HWIntrinsicInfo::lookupNumArgs(node);
 
-    assert((flags & HW_Flag_NoCodeGen) == 0);
+    assert(HWIntrinsicInfo::RequiresCodegen(intrinsicId));
 
-    if (genIsTableDrivenHWIntrinsic(category, flags))
+    if (genIsTableDrivenHWIntrinsic(intrinsicId, category))
     {
         GenTree*  op1        = node->gtGetOp1();
         GenTree*  op2        = node->gtGetOp2();
@@ -88,7 +87,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
                 {
                     emit->emitIns_R_AR(ins, simdSize, targetReg, op1Reg, 0);
                 }
-                else if (category == HW_Category_SIMDScalar && (flags & HW_Flag_CopyUpperBits) != 0)
+                else if ((category == HW_Category_SIMDScalar) && HWIntrinsicInfo::CopiesUpperBits(intrinsicId))
                 {
                     emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op1Reg);
                 }
@@ -324,7 +323,7 @@ void CodeGen::genHWIntrinsic_R_R_RM(GenTreeHWIntrinsic* node, instruction ins)
 
     if (op2->isContained() || op2->isUsedFromSpillTemp())
     {
-        assert((HWIntrinsicInfo::lookupFlags(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
+        assert(HWIntrinsicInfo::SupportsContainment(node->gtHWIntrinsicId));
 
 #if DEBUG
         bool supportsRegOptional = false;
@@ -471,7 +470,7 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins)
 
     if (op2->isContained() || op2->isUsedFromSpillTemp())
     {
-        assert((HWIntrinsicInfo::lookupFlags(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
+        assert(HWIntrinsicInfo::SupportsContainment(node->gtHWIntrinsicId));
 
 #if DEBUG
         bool supportsRegOptional = false;
@@ -1702,7 +1701,6 @@ void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node)
 {
     NamedIntrinsic  intrinsicId = node->gtHWIntrinsicId;
     var_types       baseType    = node->gtSIMDBaseType;
-    HWIntrinsicFlag flags       = HWIntrinsicInfo::lookupFlags(intrinsicId);
     emitAttr        attr        = EA_ATTR(node->gtSIMDSize);
     instruction     ins         = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
     GenTree*        op1         = node->gtGetOp1();
@@ -1730,10 +1728,10 @@ void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node)
     regNumber op2Reg;
 
     bool isCommutative = false;
-    bool copyUpperBits = (flags & HW_Flag_CopyUpperBits) != 0;
+    const bool copiesUpperBits = HWIntrinsicInfo::CopiesUpperBits(intrinsicId);
 
     // Intrinsics with CopyUpperBits semantics cannot have op1 be contained
-    assert(!copyUpperBits || !op1->isContained());
+    assert(!copiesUpperBits || !op1->isContained());
 
     if (op3->isContained() || op3->isUsedFromSpillTemp())
     {
@@ -1742,7 +1740,7 @@ void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node)
         op1Reg = op1->gtRegNum;
         op2Reg = op2->gtRegNum;
 
-        isCommutative = !copyUpperBits;
+        isCommutative = !copiesUpperBits;
     }
     else if (op2->isContained() || op2->isUsedFromSpillTemp())
     {
@@ -1769,7 +1767,7 @@ void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node)
         op1Reg = op1->gtRegNum;
         op2Reg = op2->gtRegNum;
 
-        isCommutative = !copyUpperBits;
+        isCommutative = !copiesUpperBits;
     }
 
     if (isCommutative && (op1Reg != targetReg) && (op2Reg == targetReg))
index 46119919c002329bb87f8c999510e250a82b2f30..b5d7fd42f20c9af5696e91695a427c6949a9d6d7 100644 (file)
@@ -172,7 +172,7 @@ InstructionSet HWIntrinsicInfo::lookupIsa(const char* className)
 //    get the SIMD size from the GenTreeHWIntrinsic node.
 unsigned HWIntrinsicInfo::lookupSimdSize(Compiler* comp, NamedIntrinsic id, CORINFO_SIG_INFO* sig)
 {
-    if ((lookupFlags(id) & HW_Flag_UnfixedSIMDSize) == 0)
+    if (HWIntrinsicInfo::HasFixedSimdSize(id))
     {
         return lookupSimdSize(id);
     }
@@ -185,7 +185,7 @@ unsigned HWIntrinsicInfo::lookupSimdSize(Compiler* comp, NamedIntrinsic id, CORI
     }
     else
     {
-        assert((lookupFlags(id) & HW_Flag_BaseTypeFromFirstArg) != 0);
+        assert(HWIntrinsicInfo::BaseTypeFromFirstArg(id));
         typeHnd = comp->info.compCompHnd->getArgClass(sig, sig->args);
     }
 
@@ -321,7 +321,7 @@ bool HWIntrinsicInfo::isImmOp(NamedIntrinsic id, const GenTree* op)
         return false;
     }
 
-    if ((HWIntrinsicInfo::lookupFlags(id) & HW_Flag_MaybeIMM) == 0)
+    if (!HWIntrinsicInfo::MaybeImm(id))
     {
         return true;
     }
@@ -352,13 +352,13 @@ int HWIntrinsicInfo::lookupImmUpperBound(NamedIntrinsic id)
         case NI_AVX_Compare:
         case NI_AVX_CompareScalar:
         {
-            assert((HWIntrinsicInfo::lookupFlags(id) & HW_Flag_FullRangeIMM) == 0);
+            assert(!HWIntrinsicInfo::HasFullRangeImm(id));
             return 31; // enum FloatComparisonMode has 32 values
         }
 
         default:
         {
-            assert((HWIntrinsicInfo::lookupFlags(id) & HW_Flag_FullRangeIMM) != 0);
+            assert(HWIntrinsicInfo::HasFullRangeImm(id));
             return 255;
         }
     }
@@ -486,7 +486,7 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE
 //
 GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType)
 {
-    assert((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_NoJmpTableIMM) != 0);
+    assert(HWIntrinsicInfo::NoJmpTableImm(intrinsic));
     switch (intrinsic)
     {
         case NI_SSE2_ShiftLeftLogical:
@@ -526,7 +526,7 @@ GenTree* Compiler::addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* last
     assert(lastOp != nullptr);
     // Full-range imm-intrinsics do not need the range-check
     // because the imm-parameter of the intrinsic method is a byte.
-    if (mustExpand && ((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_FullRangeIMM) == 0) &&
+    if (mustExpand && !HWIntrinsicInfo::HasFullRangeImm(intrinsic) &&
         HWIntrinsicInfo::isImmOp(intrinsic, lastOp))
     {
         assert(!lastOp->IsCnsIntOrI());
@@ -576,23 +576,22 @@ bool Compiler::compSupportsHWIntrinsic(InstructionSet isa)
 // Arguments:
 //    retType - return type
 //    sig     - intrinsic signature
-//    flags   - flags of the intrinsics
 //
 // Return Value:
 //    Returns true iff the given type signature is supported
 // Notes:
 //    - This is only used on 32-bit systems to determine whether the signature uses no 64-bit registers.
 //    - The `retType` is passed to avoid another call to the type system, as it has already been retrieved.
-bool Compiler::hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags)
+bool Compiler::hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, NamedIntrinsic intrinsic)
 {
 #ifdef _TARGET_X86_
     CORINFO_CLASS_HANDLE argClass;
 
-    if ((flags & HW_Flag_64BitOnly) != 0)
+    if (HWIntrinsicInfo::Is64BitOnly(intrinsic))
     {
         return false;
     }
-    else if ((flags & HW_Flag_SecondArgMaybe64Bit) != 0)
+    else if (HWIntrinsicInfo::SecondArgMaybe64Bit(intrinsic))
     {
         assert(sig->numArgs >= 2);
         CorInfoType corType =
@@ -615,11 +614,11 @@ bool Compiler::hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_
 // Return Value:
 //    returns true if this category can be table-driven in the importer
 //
-static bool impIsTableDrivenHWIntrinsic(HWIntrinsicCategory category, HWIntrinsicFlag flags)
+static bool impIsTableDrivenHWIntrinsic(NamedIntrinsic intrinsicId, HWIntrinsicCategory category)
 {
     // HW_Flag_NoCodeGen implies this intrinsic should be manually morphed in the importer.
-    return category != HW_Category_Special && category != HW_Category_Scalar &&
-           ((flags & (HW_Flag_NoCodeGen | HW_Flag_SpecialImport)) == 0);
+    return (category != HW_Category_Special) && (category != HW_Category_Scalar) &&
+           HWIntrinsicInfo::RequiresCodegen(intrinsicId) | !HWIntrinsicInfo::HasSpecialImport(intrinsicId);
 }
 
 //------------------------------------------------------------------------
@@ -640,7 +639,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
 {
     InstructionSet      isa      = HWIntrinsicInfo::lookupIsa(intrinsic);
     HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic);
-    HWIntrinsicFlag     flags    = HWIntrinsicInfo::lookupFlags(intrinsic);
     int                 numArgs  = sig->numArgs;
     var_types           retType  = JITtype2varType(sig->retType);
     var_types           baseType = TYP_UNKNOWN;
@@ -659,7 +657,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
     // - intrinsics do not require 64-bit registers (r64) on 32-bit platforms (signatureTypeSupproted returns
     // true)
     bool issupported =
-        compSupports(isa) && compSupportsHWIntrinsic(isa) && hwIntrinsicSignatureTypeSupported(retType, sig, flags);
+        compSupports(isa) && compSupportsHWIntrinsic(isa) && hwIntrinsicSignatureTypeSupported(retType, sig, intrinsic);
 
     if (category == HW_Category_IsSupportedProperty)
     {
@@ -676,7 +674,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
         GenTree* lastOp = impStackTop().val;
         // The imm-HWintrinsics that do not accept all imm8 values may throw
         // ArgumentOutOfRangeException when the imm argument is not in the valid range
-        if ((flags & HW_Flag_FullRangeIMM) == 0)
+        if (!HWIntrinsicInfo::HasFullRangeImm(intrinsic))
         {
             if (!mustExpand && lastOp->IsCnsIntOrI() &&
                 lastOp->AsIntCon()->IconValue() > HWIntrinsicInfo::lookupImmUpperBound(intrinsic))
@@ -687,7 +685,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
 
         if (!lastOp->IsCnsIntOrI())
         {
-            if ((flags & HW_Flag_NoJmpTableIMM) == 0 && !mustExpand)
+            if (HWIntrinsicInfo::NoJmpTableImm(intrinsic))
+            {
+                return impNonConstFallback(intrinsic, retType, baseType);
+            }
+
+            if (!mustExpand)
             {
                 // When the imm-argument is not a constant and we are not being forced to expand, we need to
                 // return nullptr so a GT_CALL to the intrinsic method is emitted instead. The
@@ -695,25 +698,21 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
                 // we emit some less efficient fallback code.
                 return nullptr;
             }
-            else if ((flags & HW_Flag_NoJmpTableIMM) != 0)
-            {
-                return impNonConstFallback(intrinsic, retType, baseType);
-            }
         }
     }
 
-    bool isTableDriven = impIsTableDrivenHWIntrinsic(category, flags);
+    bool isTableDriven = impIsTableDrivenHWIntrinsic(intrinsic, category);
 
     if (isTableDriven && ((category == HW_Category_MemoryStore) ||
-                          ((flags & (HW_Flag_BaseTypeFromFirstArg | HW_Flag_BaseTypeFromSecondArg)) != 0)))
+                          HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic) || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic)))
     {
-        if ((flags & HW_Flag_BaseTypeFromFirstArg) != 0)
+        if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic))
         {
             baseType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args));
         }
         else
         {
-            assert((category == HW_Category_MemoryStore) || ((flags & HW_Flag_BaseTypeFromSecondArg) != 0));
+            assert((category == HW_Category_MemoryStore) || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic));
             CORINFO_ARG_LIST_HANDLE secondArg      = info.compCompHnd->getArgNext(sig->args);
             CORINFO_CLASS_HANDLE    secondArgClass = info.compCompHnd->getArgClass(sig, secondArg);
             baseType                               = getBaseTypeOfSIMDType(secondArgClass);
@@ -728,14 +727,14 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
         assert(baseType != TYP_UNKNOWN);
     }
 
-    if (((flags & (HW_Flag_OneTypeGeneric | HW_Flag_TwoTypeGeneric)) != 0) && ((flags & HW_Flag_SpecialImport) == 0))
+    if ((HWIntrinsicInfo::IsOneTypeGeneric(intrinsic) || HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic)) && !HWIntrinsicInfo::HasSpecialImport(intrinsic))
     {
         if (!varTypeIsArithmetic(baseType))
         {
             return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
         }
 
-        if ((flags & HW_Flag_TwoTypeGeneric) != 0)
+        if (HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic))
         {
             // StaticCast<T, U> has two type parameters.
             assert(numArgs == 1);
@@ -747,7 +746,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
         }
     }
 
-    if ((flags & HW_Flag_NoFloatingPointUsed) == 0)
+    if (HWIntrinsicInfo::IsFloatingPointUsed(intrinsic))
     {
         // Set `compFloatingPointUsed` to cover the scenario where an intrinsic is being on SIMD fields, but
         // where no SIMD local vars are in use. This is the same logic as is used for FEATURE_SIMD.
index 4af604e3ccb076d959c64f4d7dd1fb7a0e89ed6f..dc1df77f0eb440727a7426ffd9dfbb93ca3da127 100644 (file)
@@ -200,6 +200,128 @@ struct HWIntrinsicInfo
     {
         return lookup(id).flags;
     }
+
+    // Flags lookup
+
+    static const bool IsCommutative(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_Commutative) != 0;
+    }
+
+    static const bool HasFullRangeImm(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_FullRangeIMM) != 0;
+    }
+
+    static const bool IsOneTypeGeneric(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_OneTypeGeneric) != 0;
+    }
+
+    static const bool IsTwoTypeGeneric(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_TwoTypeGeneric) != 0;
+    }
+
+    static const bool RequiresCodegen(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_NoCodeGen) == 0;
+    }
+
+    static const bool HasFixedSimdSize(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_UnfixedSIMDSize) == 0;
+    }
+
+    static const bool HasComplexOverloads(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_ComplexOverloads) != 0;
+    }
+
+    static const bool GeneratesMultipleIns(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_MultiIns) != 0;
+    }
+
+    static const bool SupportsContainment(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_NoContainment) == 0;
+    }
+
+    static const bool CopiesUpperBits(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_CopyUpperBits) != 0;
+    }
+
+    static const bool BaseTypeFromFirstArg(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_BaseTypeFromFirstArg) != 0;
+    }
+
+    static const bool IsFloatingPointUsed(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_NoFloatingPointUsed) == 0;
+    }
+
+    static const bool MaybeImm(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_MaybeIMM) != 0;
+    }
+
+    static const bool NoJmpTableImm(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_NoJmpTableIMM) != 0;
+    }
+
+    static const bool Is64BitOnly(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_64BitOnly) != 0;
+    }
+
+    static const bool SecondArgMaybe64Bit(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_SecondArgMaybe64Bit) != 0;
+    }
+
+    static const bool BaseTypeFromSecondArg(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_BaseTypeFromSecondArg) != 0;
+    }
+
+    static const bool HasSpecialCodegen(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_SpecialCodeGen) != 0;
+    }
+
+    static const bool HasRMWSemantics(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_NoRMWSemantics) == 0;
+    }
+
+    static const bool HasSpecialImport(NamedIntrinsic id)
+    {
+        HWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & HW_Flag_SpecialImport) != 0;
+    }
 };
 
 #endif // FEATURE_HW_INTRINSICS
index 49bea0d0fa47b821ac6acd5b7dc11cd1e75a6e56..27fa52a6bd02af38b958139d611718a8c3233e1b 100644 (file)
@@ -2312,7 +2312,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
     HWIntrinsicCategory category              = HWIntrinsicInfo::lookupCategory(containingIntrinsicID);
 
     // We shouldn't have called in here if containingNode doesn't support containment
-    assert((HWIntrinsicInfo::lookupFlags(containingIntrinsicID) & HW_Flag_NoContainment) == 0);
+    assert(HWIntrinsicInfo::SupportsContainment(containingIntrinsicID));
 
     // containingNode supports nodes that read from an aligned memory address
     //
@@ -2504,7 +2504,6 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
 {
     NamedIntrinsic      intrinsicID = node->gtHWIntrinsicId;
     HWIntrinsicCategory category    = HWIntrinsicInfo::lookupCategory(intrinsicID);
-    HWIntrinsicFlag     flags       = HWIntrinsicInfo::lookupFlags(intrinsicID);
     int                 numArgs     = HWIntrinsicInfo::lookupNumArgs(node);
     var_types           baseType    = node->gtSIMDBaseType;
 
@@ -2512,7 +2511,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
     GenTree* op2 = node->gtGetOp2();
     GenTree* op3 = nullptr;
 
-    if ((flags & HW_Flag_NoContainment) != 0)
+    if (!HWIntrinsicInfo::SupportsContainment(intrinsicID))
     {
         // Exit early if containment isn't supported
         return;
@@ -2520,7 +2519,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
 
     // TODO-XArch-CQ: Non-VEX encoded instructions can have both ops contained
 
-    bool isCommutative = ((flags & HW_Flag_Commutative) != 0);
+    const bool isCommutative = HWIntrinsicInfo::IsCommutative(intrinsicID);
 
     if (numArgs == 1)
     {
@@ -2613,7 +2612,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
                 {
                     // Intrinsics with CopyUpperBits semantics cannot have op1 be contained
 
-                    if ((flags & HW_Flag_CopyUpperBits) == 0)
+                    if (!HWIntrinsicInfo::CopiesUpperBits(intrinsicID))
                     {
                         // 231 form: op3 = (op2 * op3) + [op1]
                         MakeSrcContained(node, op1);
index 2a4d1b2a377f7128ea383c355b0319cf01459d46..490c8fa1adde8a9c8bc0a007729e1eefccc7e00c 100644 (file)
@@ -2294,7 +2294,6 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
     var_types           baseType    = intrinsicTree->gtSIMDBaseType;
     InstructionSet      isa         = HWIntrinsicInfo::lookupIsa(intrinsicId);
     HWIntrinsicCategory category    = HWIntrinsicInfo::lookupCategory(intrinsicId);
-    HWIntrinsicFlag     flags       = HWIntrinsicInfo::lookupFlags(intrinsicId);
     int                 numArgs     = HWIntrinsicInfo::lookupNumArgs(intrinsicTree);
 
     if ((isa == InstructionSet_AVX) || (isa == InstructionSet_AVX2))
@@ -2353,7 +2352,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
 
         bool buildUses = true;
 
-        if ((category == HW_Category_IMM) && ((flags & HW_Flag_NoJmpTableIMM) == 0))
+        if ((category == HW_Category_IMM) && !HWIntrinsicInfo::NoJmpTableImm(intrinsicId))
         {
             if (HWIntrinsicInfo::isImmOp(intrinsicId, lastOp) && !lastOp->isContainedIntOrIImmed())
             {
@@ -2522,16 +2521,16 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
                 assert(numArgs == 3);
                 assert(isRMW);
 
-                bool copyUpperBits = (flags & HW_Flag_CopyUpperBits) != 0;
+                const bool copiesUpperBits = HWIntrinsicInfo::CopiesUpperBits(intrinsicId);;
 
                 // Intrinsics with CopyUpperBits semantics cannot have op1 be contained
-                assert(!copyUpperBits || !op1->isContained());
+                assert(!copiesUpperBits || !op1->isContained());
 
                 if (op3->isContained())
                 {
                     // 213 form: op1 = (op2 * op1) + [op3]
 
-                    if (copyUpperBits)
+                    if (copiesUpperBits)
                     {
                         tgtPrefUse = BuildUse(op1);
 
@@ -2573,7 +2572,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
                 {
                     // 213 form: op1 = (op2 * op1) + op3
 
-                    if (copyUpperBits)
+                    if (copiesUpperBits)
                     {
                         tgtPrefUse = BuildUse(op1);