summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanner Gooding <tagoo@outlook.com>2018-03-07 12:15:31 -0800
committerTanner Gooding <tagoo@outlook.com>2018-03-08 08:35:05 -0800
commit530949b14c795988dd81bae603ca33a87d6ee5fd (patch)
treeed2c91249425fb6b15cfccff1e60ef0badf36a10
parent5e03df42d9fb2fe05a4246695128ddfb6e9ca7fd (diff)
downloadcoreclr-530949b14c795988dd81bae603ca33a87d6ee5fd.tar.gz
coreclr-530949b14c795988dd81bae603ca33a87d6ee5fd.tar.bz2
coreclr-530949b14c795988dd81bae603ca33a87d6ee5fd.zip
Updating isRMWRegOper, OperIsCommutative, and canBeContained to handle HWIntrinsic nodes
-rw-r--r--src/jit/compiler.h1
-rw-r--r--src/jit/gentree.cpp42
-rw-r--r--src/jit/gentree.h24
-rw-r--r--src/jit/lsraxarch.cpp29
4 files changed, 70 insertions, 26 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 7266c738e0..0d5326a9a5 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -1529,6 +1529,7 @@ class Compiler
friend class TempDsc;
friend class LIR;
friend class ObjectAllocator;
+ friend struct GenTree;
#ifndef _TARGET_64BIT_
friend class DecomposeLongs;
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp
index 9b8f88bd85..99b64312bc 100644
--- a/src/jit/gentree.cpp
+++ b/src/jit/gentree.cpp
@@ -16640,7 +16640,7 @@ bool GenTree::canBeContained() const
// It is not possible for nodes that do not produce values or that are not containable values
// to be contained.
- if ((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0)
+ if (((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0) || (OperIsHWIntrinsic() && !isContainableHWIntrinsic()))
{
return false;
}
@@ -17982,6 +17982,46 @@ bool GenTree::isCommutativeSIMDIntrinsic()
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
+bool GenTree::isCommutativeHWIntrinsic() const
+{
+ assert(gtOper == GT_HWIntrinsic);
+
+#ifdef _TARGET_XARCH_
+ HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(AsHWIntrinsic()->gtHWIntrinsicId);
+ return ((flags & HW_Flag_Commutative) != 0);
+#else
+ return false;
+#endif // _TARGET_XARCH_
+}
+
+bool GenTree::isContainableHWIntrinsic() const
+{
+ assert(gtOper == GT_HWIntrinsic);
+
+#ifdef _TARGET_XARCH_
+ HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(AsHWIntrinsic()->gtHWIntrinsicId);
+ return ((flags & HW_Flag_NoContainment) == 0);
+#else
+ return false;
+#endif // _TARGET_XARCH_
+}
+
+bool GenTree::isRMWHWIntrinsic(Compiler* comp)
+{
+ assert(gtOper == GT_HWIntrinsic);
+ assert(comp != nullptr);
+
+#ifdef _TARGET_XARCH_
+ if (!comp->canUseVexEncoding())
+ {
+ HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(AsHWIntrinsic()->gtHWIntrinsicId);
+ return ((flags & HW_Flag_NoRMWSemantics) == 0);
+ }
+#endif // _TARGET_XARCH_
+
+ return false;
+}
+
GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types type,
NamedIntrinsic hwIntrinsicID,
var_types baseType,
diff --git a/src/jit/gentree.h b/src/jit/gentree.h
index 25d5a286fd..35c215cf21 100644
--- a/src/jit/gentree.h
+++ b/src/jit/gentree.h
@@ -1471,6 +1471,27 @@ public:
}
#endif // FEATURE_SIMD
+#ifdef FEATURE_HW_INTRINSICS
+ bool isCommutativeHWIntrinsic() const;
+ bool isContainableHWIntrinsic() const;
+ bool isRMWHWIntrinsic(Compiler* comp);
+#else
+ bool isCommutativeHWIntrinsic() const
+ {
+ return false;
+ }
+
+ bool isContainableHWIntrinsic() const
+ {
+ return false;
+ }
+
+ bool isRMWHWIntrinsic(Compiler* comp)
+ {
+ return false;
+ }
+#endif // FEATURE_HW_INTRINSICS
+
static bool OperIsCommutative(genTreeOps gtOper)
{
return (OperKind(gtOper) & GTK_COMMUTE) != 0;
@@ -1478,7 +1499,8 @@ public:
bool OperIsCommutative()
{
- return OperIsCommutative(gtOper) || (OperIsSIMD(gtOper) && isCommutativeSIMDIntrinsic());
+ return OperIsCommutative(gtOper) || (OperIsSIMD(gtOper) && isCommutativeSIMDIntrinsic()) ||
+ (OperIsHWIntrinsic(gtOper) && isCommutativeHWIntrinsic());
}
static bool OperIsAssignment(genTreeOps gtOper)
diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp
index b0e95ae31f..a9f0207d8d 100644
--- a/src/jit/lsraxarch.cpp
+++ b/src/jit/lsraxarch.cpp
@@ -821,6 +821,11 @@ bool LinearScan::isRMWRegOper(GenTree* tree)
case GT_MUL:
return (!tree->gtOp.gtOp2->isContainedIntOrIImmed() && !tree->gtOp.gtOp1->isContainedIntOrIImmed());
+#ifdef FEATURE_HW_INTRINSICS
+ case GT_HWIntrinsic:
+ return tree->isRMWHWIntrinsic(compiler);
+#endif // FEATURE_HW_INTRINSICS
+
default:
return true;
}
@@ -2309,30 +2314,6 @@ void LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
}
}
- if (!compiler->canUseVexEncoding())
- {
- // On machines without VEX support, we sometimes have to inject an intermediate
- // `movaps targetReg, op1Reg` in order to maintain the correct behavior. This
- // becomes a problem if `op2Reg == targetReg` since that means we will overwrite
- // op2. In order to resolve this, we currently mark the second operand as delay free.
-
- if ((flags & HW_Flag_NoRMWSemantics) == 0)
- {
- assert(category != HW_Category_MemoryLoad);
- assert(category != HW_Category_MemoryStore);
-
- assert((flags & HW_Flag_NoCodeGen) == 0);
-
- if (info->srcCount >= 2)
- {
- assert(numArgs >= 2);
- LocationInfoListNode* op2Info = useList.Begin()->Next();
- op2Info->info.isDelayFree = true;
- info->hasDelayFreeSrc = true;
- }
- }
- }
-
switch (intrinsicID)
{
case NI_SSE_CompareEqualOrderedScalar: