Improved side-effects/can-throw information on intrinsics.
Rationale: improved side effect and exception analysis gives
many more opportunities for GVN/LICM/BCE.
Change-Id: I8aa9b757d77c7bd9d58271204a657c2c525195b5
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 7127215..c6da9a3 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -36,8 +36,8 @@
switch (i) {
case Intrinsics::kNone:
return kInterface; // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
- case Intrinsics::k ## Name: \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+ case Intrinsics::k ## Name: \
return IsStatic;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -52,8 +52,8 @@
switch (i) {
case Intrinsics::kNone:
return kNeedsEnvironmentOrCache; // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
- case Intrinsics::k ## Name: \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+ case Intrinsics::k ## Name: \
return NeedsEnvironmentOrCache;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -63,6 +63,38 @@
return kNeedsEnvironmentOrCache;
}
+// Function that returns whether an intrinsic has side effects.
+static inline IntrinsicSideEffects GetSideEffects(Intrinsics i) {
+ switch (i) {
+ case Intrinsics::kNone:
+ return kAllSideEffects;
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+ case Intrinsics::k ## Name: \
+ return SideEffects;
+#include "intrinsics_list.h"
+INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+#undef OPTIMIZING_INTRINSICS
+ }
+ return kAllSideEffects;
+}
+
+// Function that returns whether an intrinsic can throw exceptions.
+static inline IntrinsicExceptions GetExceptions(Intrinsics i) {
+ switch (i) {
+ case Intrinsics::kNone:
+ return kCanThrow;
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+ case Intrinsics::k ## Name: \
+ return Exceptions;
+#include "intrinsics_list.h"
+INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+#undef OPTIMIZING_INTRINSICS
+ }
+ return kCanThrow;
+}
+
static Primitive::Type GetType(uint64_t data, bool is_op_size) {
if (is_op_size) {
switch (static_cast<OpSize>(data)) {
@@ -248,7 +280,7 @@
// Thread.currentThread.
case kIntrinsicCurrentThread:
- return Intrinsics::kThreadCurrentThread;
+ return Intrinsics::kThreadCurrentThread;
// Memory.peek.
case kIntrinsicPeek:
@@ -473,7 +505,10 @@
<< PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
<< invoke->DebugName();
} else {
- invoke->SetIntrinsic(intrinsic, NeedsEnvironmentOrCache(intrinsic));
+ invoke->SetIntrinsic(intrinsic,
+ NeedsEnvironmentOrCache(intrinsic),
+ GetSideEffects(intrinsic),
+ GetExceptions(intrinsic));
}
}
}
@@ -487,7 +522,7 @@
case Intrinsics::kNone:
os << "None";
break;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
case Intrinsics::k ## Name: \
os << # Name; \
break;
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index a6db1e8..9f50d18 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -57,9 +57,9 @@
switch (invoke->GetIntrinsic()) {
case Intrinsics::kNone:
return;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \
- case Intrinsics::k ## Name: \
- Visit ## Name(invoke); \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
+ case Intrinsics::k ## Name: \
+ Visit ## Name(invoke); \
return;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -72,7 +72,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
}
#include "intrinsics_list.h"
diff --git a/compiler/optimizing/intrinsics_arm.h b/compiler/optimizing/intrinsics_arm.h
index 127e9a4..e01b6ff 100644
--- a/compiler/optimizing/intrinsics_arm.h
+++ b/compiler/optimizing/intrinsics_arm.h
@@ -40,7 +40,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -67,7 +67,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h
index 4250ecf..d47448a 100644
--- a/compiler/optimizing/intrinsics_arm64.h
+++ b/compiler/optimizing/intrinsics_arm64.h
@@ -41,7 +41,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -65,7 +65,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h
index 96f43a0..2e87546 100644
--- a/compiler/optimizing/intrinsics_list.h
+++ b/compiler/optimizing/intrinsics_list.h
@@ -22,97 +22,97 @@
// environment.
#define INTRINSICS_LIST(V) \
- V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache) \
- V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache) \
- V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache) \
- V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache) \
- V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache) \
- V(LongReverse, kStatic, kNeedsEnvironmentOrCache) \
- V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache) \
- V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache) \
- V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache) \
- V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache) \
- V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache) \
- V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache) \
- V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache) \
- V(MathCos, kStatic, kNeedsEnvironmentOrCache) \
- V(MathSin, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAcos, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAsin, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAtan, kStatic, kNeedsEnvironmentOrCache) \
- V(MathAtan2, kStatic, kNeedsEnvironmentOrCache) \
- V(MathCbrt, kStatic, kNeedsEnvironmentOrCache) \
- V(MathCosh, kStatic, kNeedsEnvironmentOrCache) \
- V(MathExp, kStatic, kNeedsEnvironmentOrCache) \
- V(MathExpm1, kStatic, kNeedsEnvironmentOrCache) \
- V(MathHypot, kStatic, kNeedsEnvironmentOrCache) \
- V(MathLog, kStatic, kNeedsEnvironmentOrCache) \
- V(MathLog10, kStatic, kNeedsEnvironmentOrCache) \
- V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache) \
- V(MathSinh, kStatic, kNeedsEnvironmentOrCache) \
- V(MathTan, kStatic, kNeedsEnvironmentOrCache) \
- V(MathTanh, kStatic, kNeedsEnvironmentOrCache) \
- V(MathSqrt, kStatic, kNeedsEnvironmentOrCache) \
- V(MathCeil, kStatic, kNeedsEnvironmentOrCache) \
- V(MathFloor, kStatic, kNeedsEnvironmentOrCache) \
- V(MathRint, kStatic, kNeedsEnvironmentOrCache) \
- V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache) \
- V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache) \
- V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache) \
- V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache) \
- V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache) \
- V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache) \
- V(StringCharAt, kDirect, kNeedsEnvironmentOrCache) \
- V(StringCompareTo, kDirect, kNeedsEnvironmentOrCache) \
- V(StringEquals, kDirect, kNeedsEnvironmentOrCache) \
- V(StringGetCharsNoCheck, kDirect, kNeedsEnvironmentOrCache) \
- V(StringIndexOf, kDirect, kNeedsEnvironmentOrCache) \
- V(StringIndexOfAfter, kDirect, kNeedsEnvironmentOrCache) \
- V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache) \
- V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache) \
- V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache) \
- V(UnsafeCASInt, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeCASLong, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeCASObject, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGet, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGetVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGetObject, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGetObjectVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGetLong, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafeGetLongVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePut, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutOrdered, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutObject, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutObjectOrdered, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutObjectVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutLong, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutLongOrdered, kDirect, kNeedsEnvironmentOrCache) \
- V(UnsafePutLongVolatile, kDirect, kNeedsEnvironmentOrCache) \
- V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache)
+ V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
+ V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
+ V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
+ V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
+ V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
+ V(StringCharAt, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringCompareTo, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringEquals, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringGetCharsNoCheck, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringIndexOf, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringIndexOfAfter, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
+ V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeCASInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeCASLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeCASObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGet, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGetVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGetObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGetObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGetLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafeGetLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePut, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutObjectOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutLongOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(UnsafePutLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
+ V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow)
#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
#undef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ // #define is only for lint.
diff --git a/compiler/optimizing/intrinsics_mips.h b/compiler/optimizing/intrinsics_mips.h
index 19ad525..f86b0ef 100644
--- a/compiler/optimizing/intrinsics_mips.h
+++ b/compiler/optimizing/intrinsics_mips.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -60,7 +60,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_mips64.h b/compiler/optimizing/intrinsics_mips64.h
index 1481d24..4137fbd 100644
--- a/compiler/optimizing/intrinsics_mips64.h
+++ b/compiler/optimizing/intrinsics_mips64.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -60,7 +60,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h
index fefe9c6..08bd197 100644
--- a/compiler/optimizing/intrinsics_x86.h
+++ b/compiler/optimizing/intrinsics_x86.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -61,7 +61,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h
index 6894e1b..155ff65 100644
--- a/compiler/optimizing/intrinsics_x86_64.h
+++ b/compiler/optimizing/intrinsics_x86_64.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -61,7 +61,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index a37298c..a9a2493 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2091,13 +2091,27 @@
}
void HInvoke::SetIntrinsic(Intrinsics intrinsic,
- IntrinsicNeedsEnvironmentOrCache needs_env_or_cache) {
+ IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
+ IntrinsicSideEffects side_effects,
+ IntrinsicExceptions exceptions) {
intrinsic_ = intrinsic;
IntrinsicOptimizations opt(this);
if (needs_env_or_cache == kNoEnvironmentOrCache) {
opt.SetDoesNotNeedDexCache();
opt.SetDoesNotNeedEnvironment();
}
+ // Adjust method's side effects from intrinsic table.
+ switch (side_effects) {
+ case kNoSideEffects: SetSideEffects(SideEffects::None()); break;
+ case kReadSideEffects: SetSideEffects(SideEffects::AllReads()); break;
+ case kWriteSideEffects: SetSideEffects(SideEffects::AllWrites()); break;
+ case kAllSideEffects: SetSideEffects(SideEffects::AllExceptGCDependency()); break;
+ }
+ // Adjust method's exception status from intrinsic table.
+ switch (exceptions) {
+ case kNoThrow: SetCanThrow(false); break;
+ case kCanThrow: SetCanThrow(true); break;
+ }
}
bool HInvoke::NeedsEnvironment() const {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index db3e969..ddd215d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2064,6 +2064,7 @@
protected:
virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
+ void SetSideEffects(SideEffects other) { side_effects_ = other; }
private:
void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
@@ -3247,7 +3248,8 @@
};
enum class Intrinsics {
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) k ## Name,
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+ k ## Name,
#include "intrinsics_list.h"
kNone,
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -3261,6 +3263,18 @@
kNeedsEnvironmentOrCache // Intrinsic requires an environment or requires a dex cache.
};
+enum IntrinsicSideEffects {
+ kNoSideEffects, // Intrinsic does not have any heap memory side effects.
+ kReadSideEffects, // Intrinsic may read heap memory.
+ kWriteSideEffects, // Intrinsic may write heap memory.
+ kAllSideEffects // Intrinsic may read or write heap memory, or trigger GC.
+};
+
+enum IntrinsicExceptions {
+ kNoThrow, // Intrinsic does not throw any exceptions.
+ kCanThrow // Intrinsic may throw exceptions.
+};
+
class HInvoke : public HInstruction {
public:
size_t InputCount() const OVERRIDE { return inputs_.size(); }
@@ -3279,7 +3293,6 @@
Primitive::Type GetType() const OVERRIDE { return return_type_; }
-
uint32_t GetDexMethodIndex() const { return dex_method_index_; }
const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
@@ -3289,13 +3302,22 @@
return intrinsic_;
}
- void SetIntrinsic(Intrinsics intrinsic, IntrinsicNeedsEnvironmentOrCache needs_env_or_cache);
+ void SetIntrinsic(Intrinsics intrinsic,
+ IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
+ IntrinsicSideEffects side_effects,
+ IntrinsicExceptions exceptions);
bool IsFromInlinedInvoke() const {
return GetEnvironment()->IsFromInlinedInvoke();
}
- bool CanThrow() const OVERRIDE { return true; }
+ bool CanThrow() const OVERRIDE { return can_throw_; }
+
+ bool CanBeMoved() const OVERRIDE { return IsIntrinsic(); }
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ return intrinsic_ != Intrinsics::kNone && intrinsic_ == other->AsInvoke()->intrinsic_;
+ }
uint32_t* GetIntrinsicOptimizations() {
return &intrinsic_optimizations_;
@@ -3325,6 +3347,7 @@
return_type_(return_type),
dex_method_index_(dex_method_index),
original_invoke_type_(original_invoke_type),
+ can_throw_(true),
intrinsic_(Intrinsics::kNone),
intrinsic_optimizations_(0) {
}
@@ -3337,11 +3360,14 @@
inputs_[index] = input;
}
+ void SetCanThrow(bool can_throw) { can_throw_ = can_throw; }
+
uint32_t number_of_arguments_;
ArenaVector<HUserRecord<HInstruction*>> inputs_;
const Primitive::Type return_type_;
const uint32_t dex_method_index_;
const InvokeType original_invoke_type_;
+ bool can_throw_;
Intrinsics intrinsic_;
// A magic word holding optimizations for intrinsics. See intrinsics.h.