diff options
author | 2015-12-14 11:57:01 -0800 | |
---|---|---|
committer | 2015-12-30 10:52:51 -0800 | |
commit | 5d75afe333f57546786686d9bee16b52f1bbe971 (patch) | |
tree | ee203dd8ff8c4c6257b6c1ae1db1a432a8a8682f | |
parent | 1e65a78577ed71f5e3d79edaa0e6735ea4a3371b (diff) |
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
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 49 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_list.h | 182 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_mips.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_mips64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 16 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 34 | ||||
-rw-r--r-- | test/445-checker-licm/src/Main.java | 74 | ||||
-rw-r--r-- | test/449-checker-bce/src/Main.java | 49 | ||||
-rw-r--r-- | test/455-checker-gvn/expected.txt | 2 | ||||
-rw-r--r-- | test/455-checker-gvn/src/Main.java | 53 | ||||
-rw-r--r-- | test/530-checker-loops/src/Main.java | 560 |
16 files changed, 644 insertions, 407 deletions
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 7127215c51..c6da9a3f5e 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -36,8 +36,8 @@ static inline InvokeType GetIntrinsicInvokeType(Intrinsics i) { 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 @@ static inline IntrinsicNeedsEnvironmentOrCache NeedsEnvironmentOrCache(Intrinsic 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 @@ INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 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 @@ static Intrinsics GetIntrinsic(InlineMethod method) { // Thread.currentThread. case kIntrinsicCurrentThread: - return Intrinsics::kThreadCurrentThread; + return Intrinsics::kThreadCurrentThread; // Memory.peek. case kIntrinsicPeek: @@ -473,7 +505,10 @@ void IntrinsicsRecognizer::Run() { << 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 @@ std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) { 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 a6db1e8e2a..9f50d1814e 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -57,9 +57,9 @@ class IntrinsicVisitor : public ValueObject { 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 @@ INTRINSICS_LIST(OPTIMIZING_INTRINSICS) // 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 127e9a4aa0..e01b6fffb8 100644 --- a/compiler/optimizing/intrinsics_arm.h +++ b/compiler/optimizing/intrinsics_arm.h @@ -40,7 +40,7 @@ class IntrinsicLocationsBuilderARM FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorARM FINAL : public IntrinsicVisitor { // 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 4250ecf358..d47448a9c3 100644 --- a/compiler/optimizing/intrinsics_arm64.h +++ b/compiler/optimizing/intrinsics_arm64.h @@ -41,7 +41,7 @@ class IntrinsicLocationsBuilderARM64 FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorARM64 FINAL : public IntrinsicVisitor { // 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 96f43a0f74..2e87546282 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 19ad5255d5..f86b0efe4a 100644 --- a/compiler/optimizing/intrinsics_mips.h +++ b/compiler/optimizing/intrinsics_mips.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderMIPS FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorMIPS FINAL : public IntrinsicVisitor { // 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 1481d24c9e..4137fbd1b6 100644 --- a/compiler/optimizing/intrinsics_mips64.h +++ b/compiler/optimizing/intrinsics_mips64.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderMIPS64 FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorMIPS64 FINAL : public IntrinsicVisitor { // 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 fefe9c6143..08bd197400 100644 --- a/compiler/optimizing/intrinsics_x86.h +++ b/compiler/optimizing/intrinsics_x86.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderX86 FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorX86 FINAL : public IntrinsicVisitor { // 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 6894e1b527..155ff6548b 100644 --- a/compiler/optimizing/intrinsics_x86_64.h +++ b/compiler/optimizing/intrinsics_x86_64.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderX86_64 FINAL : public IntrinsicVisitor { // 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 @@ class IntrinsicCodeGeneratorX86_64 FINAL : public IntrinsicVisitor { // 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 a37298c76e..a9a249333f 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2091,13 +2091,27 @@ bool HInstruction::HasAnyEnvironmentUseBefore(HInstruction* other) { } 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 db3e969afc..ddd215dc55 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2064,6 +2064,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { 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 @@ class HDoubleConstant : public HConstant { }; 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 @@ enum IntrinsicNeedsEnvironmentOrCache { 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 @@ class HInvoke : public HInstruction { 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 @@ class HInvoke : public HInstruction { 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 @@ class HInvoke : public HInstruction { 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 @@ class HInvoke : public HInstruction { 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. diff --git a/test/445-checker-licm/src/Main.java b/test/445-checker-licm/src/Main.java index 6ee8a4d66f..061fe6e026 100644 --- a/test/445-checker-licm/src/Main.java +++ b/test/445-checker-licm/src/Main.java @@ -52,13 +52,13 @@ public class Main { return result; } - /// CHECK-START: int Main.innerDiv2() licm (before) + /// CHECK-START: int Main.innerMul() licm (before) /// CHECK-DAG: Mul loop:B4 - /// CHECK-START: int Main.innerDiv2() licm (after) + /// CHECK-START: int Main.innerMul() licm (after) /// CHECK-DAG: Mul loop:B2 - public static int innerDiv2() { + public static int innerMul() { int result = 0; for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { @@ -71,13 +71,13 @@ public class Main { return result; } - /// CHECK-START: int Main.innerDiv3(int, int) licm (before) + /// CHECK-START: int Main.divByA(int, int) licm (before) /// CHECK-DAG: Div loop:{{B\d+}} - /// CHECK-START: int Main.innerDiv3(int, int) licm (after) + /// CHECK-START: int Main.divByA(int, int) licm (after) /// CHECK-DAG: Div loop:{{B\d+}} - public static int innerDiv3(int a, int b) { + public static int divByA(int a, int b) { int result = 0; while (b < 5) { // a might be null, so we can't hoist the operation. @@ -107,6 +107,63 @@ public class Main { return result; } + /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (before) + /// CHECK-DAG: Div loop:{{B\d+}} + + /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (after) + /// CHECK-NOT: Div loop:{{B\d+}} + + /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (after) + /// CHECK-DAG: Div loop:none + + public static int divAndIntrinsic(int[] array) { + int result = 0; + for (int i = 0; i < array.length; i++) { + // An intrinsic call, unlike a general method call, cannot modify the field value. + // As a result, the invariant division on the field can be moved out of the loop. + result += (staticField / 42) + Math.abs(array[i]); + } + return result; + } + + /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (before) + /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}} + + /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (after) + /// CHECK-NOT: InvokeStaticOrDirect loop:{{B\d+}} + + /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (after) + /// CHECK-DAG: InvokeStaticOrDirect loop:none + + public static int invariantBoundIntrinsic(int x) { + int result = 0; + // The intrinsic call to abs used as loop bound is invariant. + // As a result, the call itself can be moved out of the loop header. + for (int i = 0; i < Math.abs(x); i++) { + result += i; + } + return result; + } + + /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (before) + /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}} + + /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (after) + /// CHECK-NOT: InvokeStaticOrDirect loop:{{B\d+}} + + /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (after) + /// CHECK-DAG: InvokeStaticOrDirect loop:none + + public static int invariantBodyIntrinsic(int x, int y) { + int result = 0; + for (int i = 0; i < 10; i++) { + // The intrinsic call to max used inside the loop is invariant. + // As a result, the call itself can be moved out of the loop body. + result += Math.max(x, y); + } + return result; + } + public static int staticField = 42; public static void assertEquals(int expected, int actual) { @@ -118,6 +175,11 @@ public class Main { public static void main(String[] args) { assertEquals(10, div()); assertEquals(100, innerDiv()); + assertEquals(18900, innerMul()); + assertEquals(105, divByA(2, 0)); assertEquals(12, arrayLength(new int[] { 4, 8 })); + assertEquals(21, divAndIntrinsic(new int[] { 4, -2, 8, -3 })); + assertEquals(45, invariantBoundIntrinsic(-10)); + assertEquals(30, invariantBodyIntrinsic(2, 3)); } } diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java index c3d2759f1b..6e7ba406e0 100644 --- a/test/449-checker-bce/src/Main.java +++ b/test/449-checker-bce/src/Main.java @@ -616,6 +616,40 @@ public class Main { } } + static int[][] mA; + + /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before) + /// CHECK-DAG: NullCheck + /// CHECK-DAG: ArrayLength + /// CHECK-DAG: BoundsCheck + /// CHECK-DAG: ArrayGet + /// CHECK-DAG: NullCheck + /// CHECK-DAG: ArrayLength + /// CHECK-DAG: BoundsCheck + /// CHECK-DAG: ArrayGet + /// CHECK-DAG: InvokeStaticOrDirect + /// CHECK-DAG: ArraySet + + /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) + /// CHECK-NOT: NullCheck + /// CHECK-NOT: ArrayLength + /// CHECK-NOT: BoundsCheck + /// CHECK-DAG: ArrayGet + /// CHECK-NOT: ArrayGet + /// CHECK-DAG: InvokeStaticOrDirect + /// CHECK-DAG: ArraySet + /// CHECK-DAG: Exit + /// CHECK-DAG: Deoptimize + + static void dynamicBCEAndIntrinsic(int n) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + // Since intrinsic call cannot modify fields or arrays, + // dynamic BCE and hoisting can be applied to the inner loop. + mA[i][j] = Math.abs(mA[i][j]); + } + } + } static int foo() { try { @@ -1225,6 +1259,21 @@ public class Main { } } + mA = new int[4][4]; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + mA[i][j] = -1; + } + } + dynamicBCEAndIntrinsic(4); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (mA[i][i] != 1) { + System.out.println("dynamic bce failed!"); + } + } + } + array = new int[7]; pyramid1(array); if (!isPyramid(array)) { diff --git a/test/455-checker-gvn/expected.txt b/test/455-checker-gvn/expected.txt index 8351c19397..c1679c72e8 100644 --- a/test/455-checker-gvn/expected.txt +++ b/test/455-checker-gvn/expected.txt @@ -1 +1,3 @@ 14 +0 +10 diff --git a/test/455-checker-gvn/src/Main.java b/test/455-checker-gvn/src/Main.java index 9824f27815..cea0959979 100644 --- a/test/455-checker-gvn/src/Main.java +++ b/test/455-checker-gvn/src/Main.java @@ -15,8 +15,14 @@ */ public class Main { + + private static int mX = 2; + private static int mY = -3; + public static void main(String[] args) { System.out.println(foo(3, 4)); + System.out.println(mulAndIntrinsic()); + System.out.println(directIntrinsic(-5)); } /// CHECK-START: int Main.foo(int, int) GVN (before) @@ -35,7 +41,50 @@ public class Main { return sum1 + sum2; } - public static long bar(int i) { - return i; + /// CHECK-START: int Main.mulAndIntrinsic() GVN (before) + /// CHECK: StaticFieldGet + /// CHECK: StaticFieldGet + /// CHECK: Mul + /// CHECK: InvokeStaticOrDirect + /// CHECK: StaticFieldGet + /// CHECK: StaticFieldGet + /// CHECK: Mul + /// CHECK: Add + + /// CHECK-START: int Main.mulAndIntrinsic() GVN (after) + /// CHECK: StaticFieldGet + /// CHECK: StaticFieldGet + /// CHECK: Mul + /// CHECK: InvokeStaticOrDirect + /// CHECK-NOT: StaticFieldGet + /// CHECK-NOT: StaticFieldGet + /// CHECK-NOT: Mul + /// CHECK: Add + + public static int mulAndIntrinsic() { + // The intermediate call to abs() does not kill + // the common subexpression on the multiplication. + int mul1 = mX * mY; + int abs = Math.abs(mul1); + int mul2 = mY * mX; + return abs + mul2; } + + /// CHECK-START: int Main.directIntrinsic(int) GVN (before) + /// CHECK: InvokeStaticOrDirect + /// CHECK: InvokeStaticOrDirect + /// CHECK: Add + + /// CHECK-START: int Main.directIntrinsic(int) GVN (after) + /// CHECK: InvokeStaticOrDirect + /// CHECK-NOT: InvokeStaticOrDirect + /// CHECK: Add + + public static int directIntrinsic(int x) { + // Here, the two calls to abs() themselves can be replaced with just one. + int abs1 = Math.abs(x); + int abs2 = Math.abs(x); + return abs1 + abs2; + } + } diff --git a/test/530-checker-loops/src/Main.java b/test/530-checker-loops/src/Main.java index e827b1ed78..e93ed8fcca 100644 --- a/test/530-checker-loops/src/Main.java +++ b/test/530-checker-loops/src/Main.java @@ -26,7 +26,7 @@ public class Main { // /// CHECK-START: int Main.linear(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linear(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -40,7 +40,7 @@ public class Main { } /// CHECK-START: int Main.linearDown(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearDown(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -54,7 +54,7 @@ public class Main { } /// CHECK-START: int Main.linearObscure(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearObscure(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -69,7 +69,7 @@ public class Main { } /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -84,7 +84,7 @@ public class Main { } /// CHECK-START: int Main.hiddenStride(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.hiddenStride(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -101,7 +101,7 @@ public class Main { } /// CHECK-START: int Main.linearWhile(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWhile(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -116,7 +116,7 @@ public class Main { } /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -134,7 +134,7 @@ public class Main { } /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -156,7 +156,7 @@ public class Main { } /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -173,7 +173,7 @@ public class Main { } /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -194,7 +194,7 @@ public class Main { } /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after) /// CHECK-NOT: BoundsCheck @@ -208,7 +208,7 @@ public class Main { } /// CHECK-START: int[] Main.linearCopy(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int[] Main.linearCopy(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -223,8 +223,8 @@ public class Main { } /// CHECK-START: int Main.linearByTwo(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearByTwo(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -241,7 +241,7 @@ public class Main { } /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (after) /// CHECK-NOT: BoundsCheck @@ -255,10 +255,10 @@ public class Main { } /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int linearByTwoSkip2(int x[]) { int result = 0; @@ -270,7 +270,7 @@ public class Main { } /// CHECK-START: int Main.linearWithCompoundStride() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWithCompoundStride() BCE (after) /// CHECK-NOT: BoundsCheck @@ -287,7 +287,7 @@ public class Main { } /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after) /// CHECK-NOT: BoundsCheck @@ -305,10 +305,10 @@ public class Main { } /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int linearWithVeryLargePositiveStride() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; @@ -323,7 +323,7 @@ public class Main { } /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after) /// CHECK-NOT: BoundsCheck @@ -341,10 +341,10 @@ public class Main { } /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int linearWithVeryLargeNegativeStride() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; @@ -359,7 +359,7 @@ public class Main { } /// CHECK-START: int Main.linearForNEUp() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearForNEUp() BCE (after) /// CHECK-NOT: BoundsCheck @@ -374,7 +374,7 @@ public class Main { } /// CHECK-START: int Main.linearForNEDown() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearForNEDown() BCE (after) /// CHECK-NOT: BoundsCheck @@ -389,7 +389,7 @@ public class Main { } /// CHECK-START: int Main.linearDoWhileUp() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearDoWhileUp() BCE (after) /// CHECK-NOT: BoundsCheck @@ -405,7 +405,7 @@ public class Main { } /// CHECK-START: int Main.linearDoWhileDown() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearDoWhileDown() BCE (after) /// CHECK-NOT: BoundsCheck @@ -421,10 +421,10 @@ public class Main { } /// CHECK-START: int Main.linearShort() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.linearShort() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int linearShort() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; @@ -437,7 +437,7 @@ public class Main { } /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after) /// CHECK-NOT: BoundsCheck @@ -458,20 +458,20 @@ public class Main { } /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static void linearTriangularOnTwoArrayLengths(int n) { int[] a = new int[n]; @@ -488,20 +488,20 @@ public class Main { } /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static void linearTriangularOnOneArrayLength(int n) { int[] a = new int[n]; @@ -518,20 +518,20 @@ public class Main { } /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static void linearTriangularOnParameter(int n) { int[] a = new int[n]; @@ -548,32 +548,32 @@ public class Main { } /// CHECK-START: void Main.linearTriangularVariations(int) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: void Main.linearTriangularVariations(int) BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static void linearTriangularVariations(int n) { int[] a = new int[n]; @@ -616,22 +616,22 @@ public class Main { } /// CHECK-START: void Main.bubble(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: If - /// CHECK-DAG: ArraySet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: If + /// CHECK: ArraySet + /// CHECK: ArraySet // /// CHECK-START: void Main.bubble(int[]) BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: ArrayGet /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: If - /// CHECK-DAG: ArraySet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: If + /// CHECK: ArraySet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static void bubble(int[] a) { for (int i = a.length; --i >= 0;) { @@ -646,7 +646,7 @@ public class Main { } /// CHECK-START: int Main.periodicIdiom(int) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.periodicIdiom(int) BCE (after) /// CHECK-NOT: BoundsCheck @@ -664,7 +664,7 @@ public class Main { } /// CHECK-START: int Main.periodicSequence2(int) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.periodicSequence2(int) BCE (after) /// CHECK-NOT: BoundsCheck @@ -685,10 +685,10 @@ public class Main { } /// CHECK-START: int Main.periodicSequence4(int) BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.periodicSequence4(int) BCE (after) /// CHECK-NOT: BoundsCheck @@ -713,7 +713,7 @@ public class Main { } /// CHECK-START: int Main.justRightUp1() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightUp1() BCE (after) /// CHECK-NOT: BoundsCheck @@ -728,7 +728,7 @@ public class Main { } /// CHECK-START: int Main.justRightUp2() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightUp2() BCE (after) /// CHECK-NOT: BoundsCheck @@ -743,7 +743,7 @@ public class Main { } /// CHECK-START: int Main.justRightUp3() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightUp3() BCE (after) /// CHECK-NOT: BoundsCheck @@ -758,10 +758,10 @@ public class Main { } /// CHECK-START: int Main.justOOBUp() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justOOBUp() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int justOOBUp() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; @@ -774,7 +774,7 @@ public class Main { } /// CHECK-START: int Main.justRightDown1() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightDown1() BCE (after) /// CHECK-NOT: BoundsCheck @@ -789,7 +789,7 @@ public class Main { } /// CHECK-START: int Main.justRightDown2() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightDown2() BCE (after) /// CHECK-NOT: BoundsCheck @@ -804,7 +804,7 @@ public class Main { } /// CHECK-START: int Main.justRightDown3() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justRightDown3() BCE (after) /// CHECK-NOT: BoundsCheck @@ -819,10 +819,10 @@ public class Main { } /// CHECK-START: int Main.justOOBDown() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.justOOBDown() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static int justOOBDown() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; @@ -835,10 +835,10 @@ public class Main { } /// CHECK-START: void Main.lowerOOB(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: void Main.lowerOOB(int[]) BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static void lowerOOB(int[] x) { for (int i = -1; i < x.length; i++) { @@ -847,10 +847,10 @@ public class Main { } /// CHECK-START: void Main.upperOOB(int[]) BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: void Main.upperOOB(int[]) BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static void upperOOB(int[] x) { for (int i = 0; i <= x.length; i++) { @@ -859,10 +859,10 @@ public class Main { } /// CHECK-START: void Main.doWhileUpOOB() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: void Main.doWhileUpOOB() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static void doWhileUpOOB() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; @@ -873,10 +873,10 @@ public class Main { } /// CHECK-START: void Main.doWhileDownOOB() BCE (before) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: void Main.doWhileDownOOB() BCE (after) - /// CHECK-DAG: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: Deoptimize private static void doWhileDownOOB() { int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; @@ -887,14 +887,14 @@ public class Main { } /// CHECK-START: int[] Main.multiply1() BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: int[] Main.multiply1() BCE (after) /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: ArrayGet + /// CHECK: ArraySet /// CHECK-NOT: Deoptimize private static int[] multiply1() { int[] a = new int[10]; @@ -912,14 +912,14 @@ public class Main { } /// CHECK-START: int[] Main.multiply2() BCE (before) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet // /// CHECK-START: int[] Main.multiply2() BCE (after) - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: ArraySet static int[] multiply2() { int[] a = new int[10]; try { @@ -936,24 +936,24 @@ public class Main { } /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before) - /// CHECK-DAG: StaticFieldGet - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: StaticFieldSet + /// CHECK: StaticFieldGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: StaticFieldSet // /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after) - /// CHECK-DAG: StaticFieldGet + /// CHECK: StaticFieldGet /// CHECK-NOT: NullCheck /// CHECK-NOT: ArrayLength /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: StaticFieldSet - /// CHECK-DAG: Exit - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: ArrayGet + /// CHECK: StaticFieldSet + /// CHECK: Exit + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize private static int linearDynamicBCE1(int[] x, int lo, int hi) { int result = 0; for (int i = lo; i < hi; i++) { @@ -963,24 +963,24 @@ public class Main { } /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before) - /// CHECK-DAG: StaticFieldGet - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: StaticFieldSet + /// CHECK: StaticFieldGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: StaticFieldSet // /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after) - /// CHECK-DAG: StaticFieldGet + /// CHECK: StaticFieldGet /// CHECK-NOT: NullCheck /// CHECK-NOT: ArrayLength /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: StaticFieldSet - /// CHECK-DAG: Exit - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: ArrayGet + /// CHECK: StaticFieldSet + /// CHECK: Exit + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) { int result = 0; for (int i = lo; i < hi; i++) { @@ -990,19 +990,19 @@ public class Main { } /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after) - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize /// CHECK-NOT: NullCheck /// CHECK-NOT: ArrayLength /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: ArrayGet private static int wrapAroundDynamicBCE(int[] x) { int w = 9; int result = 0; @@ -1014,19 +1014,19 @@ public class Main { } /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after) - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize /// CHECK-NOT: NullCheck /// CHECK-NOT: ArrayLength /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: ArrayGet private static int periodicDynamicBCE(int[] x) { int k = 0; int result = 0; @@ -1038,20 +1038,20 @@ public class Main { } /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after) /// CHECK-NOT: NullCheck /// CHECK-NOT: ArrayLength /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Exit - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Exit + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) { // This loop could be infinite for hi = max int. Since i is also used // as subscript, however, dynamic bce can proceed. @@ -1063,16 +1063,16 @@ public class Main { } /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet /// CHECK-NOT: Deoptimize static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) { // As above, but now the index is not used as subscript, @@ -1085,16 +1085,16 @@ public class Main { } /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet /// CHECK-NOT: Deoptimize static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) { int result = 0; @@ -1107,41 +1107,41 @@ public class Main { } /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: NotEqual - /// CHECK-DAG: If - /// CHECK-DAG: If - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: If - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: NotEqual + /// CHECK: If + /// CHECK: If + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: If + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck // /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after) - /// CHECK-DAG: NullCheck - /// CHECK-DAG: ArrayLength - /// CHECK-DAG: NotEqual - /// CHECK-DAG: If - /// CHECK-DAG: If + /// CHECK: NullCheck + /// CHECK: ArrayLength + /// CHECK: NotEqual + /// CHECK: If + /// CHECK: If /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: If - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: If + /// CHECK: Deoptimize + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck + /// CHECK: BoundsCheck /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: Exit - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize + /// CHECK: Exit + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize /// CHECK-NOT: ArrayGet static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) { // Deliberately test array length on a before the loop so that only bounds checks @@ -1167,65 +1167,65 @@ public class Main { } /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (before) - /// CHECK-DAG: If - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: If + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet + /// CHECK: BoundsCheck + /// CHECK: ArrayGet // /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (after) - /// CHECK-DAG: If + /// CHECK: If /// CHECK-NOT: BoundsCheck - /// CHECK-DAG: ArrayGet + /// CHECK: ArrayGet /// CHECK-NOT: BoundsCheck /// CHECK-NOT: ArrayGet - /// CHECK-DAG: Exit - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: Deoptimize - /// CHECK-DAG: ArrayGet + /// CHECK: Exit + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK: ArrayGet static int dynamicBCEAndConstantIndicesAllTypes(int[] q, boolean[] r, byte[] s, |