summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2016-04-13 16:41:35 -0700
committer Aart Bik <ajcbik@google.com> 2016-04-15 10:49:34 -0700
commit18b36abc7cc03076fe1c399c0bb8ec8793cc6806 (patch)
tree3e38ee71b94c7bbde6f93976e16416a2f6d33ee0
parentdefccc564481c2c892792680c6abb6020e36bacd (diff)
Remove the no-longer-needed F/I and D/J alias.
Rationale: Now that our HIR is type clean (yeah!), we no longer have to conservatively assume F/I and D/J are aliased. This enables more accurate side effects analysis, with improvements in all clients, such a LICM. Refinement: The HIR is not completely clean between building and SSA. This refinement takes care of that, with new tests. BUG=22538329 Change-Id: Id78ff0ff4e325aeebf0022d868937cff73d3a742
-rw-r--r--compiler/optimizing/licm_test.cc12
-rw-r--r--compiler/optimizing/nodes.h52
-rw-r--r--compiler/optimizing/side_effects_test.cc34
-rw-r--r--compiler/optimizing/ssa_builder.cc3
-rw-r--r--test/525-checker-arrays-and-fields/expected.txt0
-rw-r--r--test/525-checker-arrays-and-fields/info.txt1
-rw-r--r--test/525-checker-arrays-fields1/expected.txt1
-rw-r--r--test/525-checker-arrays-fields1/info.txt1
-rw-r--r--test/525-checker-arrays-fields1/src/Main.java711
-rw-r--r--test/525-checker-arrays-fields2/expected.txt1
-rw-r--r--test/525-checker-arrays-fields2/info.txt1
-rw-r--r--test/525-checker-arrays-fields2/src/Main.java (renamed from test/525-checker-arrays-and-fields/src/Main.java)638
-rw-r--r--test/594-checker-array-alias/expected.txt1
-rw-r--r--test/594-checker-array-alias/info.txt1
-rw-r--r--test/594-checker-array-alias/src/Main.java255
15 files changed, 1145 insertions, 567 deletions
diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc
index d446539700..2a62643465 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -169,13 +169,11 @@ TEST_F(LICMTest, ArrayHoisting) {
BuildLoop();
// Populate the loop with instructions: set/get array with different types.
- // ArrayGet is typed as kPrimByte and ArraySet given a float value in order to
- // avoid SsaBuilder's typing of ambiguous array operations from reference type info.
HInstruction* get_array = new (&allocator_) HArrayGet(
- parameter_, int_constant_, Primitive::kPrimByte, 0);
+ parameter_, int_constant_, Primitive::kPrimInt, 0);
loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction());
HInstruction* set_array = new (&allocator_) HArraySet(
- parameter_, int_constant_, float_constant_, Primitive::kPrimShort, 0);
+ parameter_, int_constant_, float_constant_, Primitive::kPrimFloat, 0);
loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction());
EXPECT_EQ(get_array->GetBlock(), loop_body_);
@@ -189,13 +187,11 @@ TEST_F(LICMTest, NoArrayHoisting) {
BuildLoop();
// Populate the loop with instructions: set/get array with same types.
- // ArrayGet is typed as kPrimByte and ArraySet given a float value in order to
- // avoid SsaBuilder's typing of ambiguous array operations from reference type info.
HInstruction* get_array = new (&allocator_) HArrayGet(
- parameter_, int_constant_, Primitive::kPrimByte, 0);
+ parameter_, int_constant_, Primitive::kPrimFloat, 0);
loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction());
HInstruction* set_array = new (&allocator_) HArraySet(
- parameter_, get_array, float_constant_, Primitive::kPrimByte, 0);
+ parameter_, get_array, float_constant_, Primitive::kPrimFloat, 0);
loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction());
EXPECT_EQ(get_array->GetBlock(), loop_body_);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index dc5a8fa9cb..8b64fe0201 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1551,21 +1551,21 @@ class SideEffects : public ValueObject {
static SideEffects FieldWriteOfType(Primitive::Type type, bool is_volatile) {
return is_volatile
? AllWritesAndReads()
- : SideEffects(TypeFlagWithAlias(type, kFieldWriteOffset));
+ : SideEffects(TypeFlag(type, kFieldWriteOffset));
}
static SideEffects ArrayWriteOfType(Primitive::Type type) {
- return SideEffects(TypeFlagWithAlias(type, kArrayWriteOffset));
+ return SideEffects(TypeFlag(type, kArrayWriteOffset));
}
static SideEffects FieldReadOfType(Primitive::Type type, bool is_volatile) {
return is_volatile
? AllWritesAndReads()
- : SideEffects(TypeFlagWithAlias(type, kFieldReadOffset));
+ : SideEffects(TypeFlag(type, kFieldReadOffset));
}
static SideEffects ArrayReadOfType(Primitive::Type type) {
- return SideEffects(TypeFlagWithAlias(type, kArrayReadOffset));
+ return SideEffects(TypeFlag(type, kArrayReadOffset));
}
static SideEffects CanTriggerGC() {
@@ -1692,23 +1692,6 @@ class SideEffects : public ValueObject {
static constexpr uint64_t kAllReads =
((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
- // Work around the fact that HIR aliases I/F and J/D.
- // TODO: remove this interceptor once HIR types are clean
- static uint64_t TypeFlagWithAlias(Primitive::Type type, int offset) {
- switch (type) {
- case Primitive::kPrimInt:
- case Primitive::kPrimFloat:
- return TypeFlag(Primitive::kPrimInt, offset) |
- TypeFlag(Primitive::kPrimFloat, offset);
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- return TypeFlag(Primitive::kPrimLong, offset) |
- TypeFlag(Primitive::kPrimDouble, offset);
- default:
- return TypeFlag(type, offset);
- }
- }
-
// Translates type to bit flag.
static uint64_t TypeFlag(Primitive::Type type, int offset) {
CHECK_NE(type, Primitive::kPrimVoid);
@@ -5137,14 +5120,8 @@ class HInstanceFieldSet : public HTemplateInstruction<2> {
class HArrayGet : public HExpression<2> {
public:
- HArrayGet(HInstruction* array,
- HInstruction* index,
- Primitive::Type type,
- uint32_t dex_pc,
- SideEffects additional_side_effects = SideEffects::None())
- : HExpression(type,
- SideEffects::ArrayReadOfType(type).Union(additional_side_effects),
- dex_pc) {
+ HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type, uint32_t dex_pc)
+ : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
}
@@ -5193,13 +5170,8 @@ class HArraySet : public HTemplateInstruction<3> {
HInstruction* index,
HInstruction* value,
Primitive::Type expected_component_type,
- uint32_t dex_pc,
- SideEffects additional_side_effects = SideEffects::None())
- : HTemplateInstruction(
- SideEffects::ArrayWriteOfType(expected_component_type).Union(
- SideEffectsForArchRuntimeCalls(value->GetType())).Union(
- additional_side_effects),
- dex_pc) {
+ uint32_t dex_pc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {
SetPackedField<ExpectedComponentTypeField>(expected_component_type);
SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == Primitive::kPrimNot);
SetPackedFlag<kFlagValueCanBeNull>(true);
@@ -5207,6 +5179,8 @@ class HArraySet : public HTemplateInstruction<3> {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
SetRawInputAt(2, value);
+ // Make a best guess now, may be refined during SSA building.
+ ComputeSideEffects();
}
bool NeedsEnvironment() const OVERRIDE {
@@ -5259,6 +5233,12 @@ class HArraySet : public HTemplateInstruction<3> {
return GetPackedField<ExpectedComponentTypeField>();
}
+ void ComputeSideEffects() {
+ Primitive::Type type = GetComponentType();
+ SetSideEffects(SideEffects::ArrayWriteOfType(type).Union(
+ SideEffectsForArchRuntimeCalls(type)));
+ }
+
static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) {
return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None();
}
diff --git a/compiler/optimizing/side_effects_test.cc b/compiler/optimizing/side_effects_test.cc
index 9bbc354290..b01bc1ca0d 100644
--- a/compiler/optimizing/side_effects_test.cc
+++ b/compiler/optimizing/side_effects_test.cc
@@ -148,19 +148,19 @@ TEST(SideEffectsTest, VolatileDependences) {
EXPECT_FALSE(any_write.MayDependOn(volatile_read));
}
-TEST(SideEffectsTest, SameWidthTypes) {
+TEST(SideEffectsTest, SameWidthTypesNoAlias) {
// Type I/F.
- testWriteAndReadDependence(
+ testNoWriteAndReadDependence(
SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ false),
SideEffects::FieldReadOfType(Primitive::kPrimFloat, /* is_volatile */ false));
- testWriteAndReadDependence(
+ testNoWriteAndReadDependence(
SideEffects::ArrayWriteOfType(Primitive::kPrimInt),
SideEffects::ArrayReadOfType(Primitive::kPrimFloat));
// Type L/D.
- testWriteAndReadDependence(
+ testNoWriteAndReadDependence(
SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false),
SideEffects::FieldReadOfType(Primitive::kPrimDouble, /* is_volatile */ false));
- testWriteAndReadDependence(
+ testNoWriteAndReadDependence(
SideEffects::ArrayWriteOfType(Primitive::kPrimLong),
SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
}
@@ -216,14 +216,32 @@ TEST(SideEffectsTest, BitStrings) {
"||||||L|",
SideEffects::FieldWriteOfType(Primitive::kPrimNot, false).ToString().c_str());
EXPECT_STREQ(
+ "||DFJISCBZL|DFJISCBZL||DFJISCBZL|DFJISCBZL|",
+ SideEffects::FieldWriteOfType(Primitive::kPrimNot, true).ToString().c_str());
+ EXPECT_STREQ(
"|||||Z||",
SideEffects::ArrayWriteOfType(Primitive::kPrimBoolean).ToString().c_str());
EXPECT_STREQ(
+ "|||||C||",
+ SideEffects::ArrayWriteOfType(Primitive::kPrimChar).ToString().c_str());
+ EXPECT_STREQ(
+ "|||||S||",
+ SideEffects::ArrayWriteOfType(Primitive::kPrimShort).ToString().c_str());
+ EXPECT_STREQ(
"|||B||||",
SideEffects::FieldReadOfType(Primitive::kPrimByte, false).ToString().c_str());
EXPECT_STREQ(
- "||DJ|||||", // note: DJ alias
+ "||D|||||",
SideEffects::ArrayReadOfType(Primitive::kPrimDouble).ToString().c_str());
+ EXPECT_STREQ(
+ "||J|||||",
+ SideEffects::ArrayReadOfType(Primitive::kPrimLong).ToString().c_str());
+ EXPECT_STREQ(
+ "||F|||||",
+ SideEffects::ArrayReadOfType(Primitive::kPrimFloat).ToString().c_str());
+ EXPECT_STREQ(
+ "||I|||||",
+ SideEffects::ArrayReadOfType(Primitive::kPrimInt).ToString().c_str());
SideEffects s = SideEffects::None();
s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimChar, /* is_volatile */ false));
s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false));
@@ -231,9 +249,7 @@ TEST(SideEffectsTest, BitStrings) {
s = s.Union(SideEffects::FieldReadOfType(Primitive::kPrimInt, /* is_volatile */ false));
s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimFloat));
s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
- EXPECT_STREQ(
- "||DFJI|FI||S|DJC|", // note: DJ/FI alias.
- s.ToString().c_str());
+ EXPECT_STREQ("||DF|I||S|JC|", s.ToString().c_str());
}
} // namespace art
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index eeadbeb0d1..2fe2f2053a 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -391,6 +391,9 @@ bool SsaBuilder::FixAmbiguousArrayOps() {
worklist.push_back(equivalent->AsPhi());
}
}
+ // Refine the side effects of this floating point aset. Note that we do this even if
+ // no replacement occurs, since the right-hand-side may have been corrected already.
+ aset->ComputeSideEffects();
} else {
// Array elements are integral and the value assigned to it initially
// was integral too. Nothing to do.
diff --git a/test/525-checker-arrays-and-fields/expected.txt b/test/525-checker-arrays-and-fields/expected.txt
deleted file mode 100644
index e69de29bb2..0000000000
--- a/test/525-checker-arrays-and-fields/expected.txt
+++ /dev/null
diff --git a/test/525-checker-arrays-and-fields/info.txt b/test/525-checker-arrays-and-fields/info.txt
deleted file mode 100644
index 3e16abf204..0000000000
--- a/test/525-checker-arrays-and-fields/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test on (in)variant static and instance field and array references in loops.
diff --git a/test/525-checker-arrays-fields1/expected.txt b/test/525-checker-arrays-fields1/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/525-checker-arrays-fields1/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/525-checker-arrays-fields1/info.txt b/test/525-checker-arrays-fields1/info.txt
new file mode 100644
index 0000000000..7d0a088934
--- /dev/null
+++ b/test/525-checker-arrays-fields1/info.txt
@@ -0,0 +1 @@
+Test on (in)variant static field and array references in loops.
diff --git a/test/525-checker-arrays-fields1/src/Main.java b/test/525-checker-arrays-fields1/src/Main.java
new file mode 100644
index 0000000000..ba0476af5f
--- /dev/null
+++ b/test/525-checker-arrays-fields1/src/Main.java
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Test on (in)variant static field and array references in loops.
+//
+public class Main {
+
+ private static Object anObject = new Object();
+ private static Object anotherObject = new Object();
+
+ //
+ // Static fields.
+ //
+
+ private static boolean sZ;
+ private static byte sB;
+ private static char sC;
+ private static short sS;
+ private static int sI;
+ private static long sJ;
+ private static float sF;
+ private static double sD;
+ private static Object sL;
+
+ //
+ // Static arrays.
+ //
+
+ private static boolean[] sArrZ;
+ private static byte[] sArrB;
+ private static char[] sArrC;
+ private static short[] sArrS;
+ private static int[] sArrI;
+ private static long[] sArrJ;
+ private static float[] sArrF;
+ private static double[] sArrD;
+ private static Object[] sArrL;
+
+ //
+ // Loops on static arrays with invariant static field references.
+ // The checker is used to ensure hoisting occurred.
+ //
+
+ /// CHECK-START: void Main.InvLoopZ() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopZ() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopZ() {
+ for (int i = 0; i < sArrZ.length; i++) {
+ sArrZ[i] = sZ;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopB() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopB() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopB() {
+ for (int i = 0; i < sArrB.length; i++) {
+ sArrB[i] = sB;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopC() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopC() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopC() {
+ for (int i = 0; i < sArrC.length; i++) {
+ sArrC[i] = sC;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopS() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopS() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopS() {
+ for (int i = 0; i < sArrS.length; i++) {
+ sArrS[i] = sS;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopI() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopI() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopI() {
+ for (int i = 0; i < sArrI.length; i++) {
+ sArrI[i] = sI;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopJ() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopJ() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopJ() {
+ for (int i = 0; i < sArrJ.length; i++) {
+ sArrJ[i] = sJ;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopF() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopF() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopF() {
+ for (int i = 0; i < sArrF.length; i++) {
+ sArrF[i] = sF;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopD() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopD() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopD() {
+ for (int i = 0; i < sArrD.length; i++) {
+ sArrD[i] = sD;
+ }
+ }
+
+ /// CHECK-START: void Main.InvLoopL() licm (before)
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+ /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.InvLoopL() licm (after)
+ /// CHECK-DAG: StaticFieldGet loop:none
+ /// CHECK-DAG: StaticFieldGet loop:none
+
+ private static void InvLoopL() {
+ for (int i = 0; i < sArrL.length; i++) {
+ sArrL[i] = sL;
+ }
+ }
+
+ //
+ // Loops on static arrays with variant static field references.
+ // Incorrect hoisting is detected by incorrect outcome.
+ //
+
+ private static void VarLoopZ() {
+ for (int i = 0; i < sArrZ.length; i++) {
+ sArrZ[i] = sZ;
+ if (i == 10)
+ sZ = !sZ;
+ }
+ }
+
+ private static void VarLoopB() {
+ for (int i = 0; i < sArrB.length; i++) {
+ sArrB[i] = sB;
+ if (i == 10)
+ sB++;
+ }
+ }
+
+ private static void VarLoopC() {
+ for (int i = 0; i < sArrC.length; i++) {
+ sArrC[i] = sC;
+ if (i == 10)
+ sC++;
+ }
+ }
+
+ private static void VarLoopS() {
+ for (int i = 0; i < sArrS.length; i++) {
+ sArrS[i] = sS;
+ if (i == 10)
+ sS++;
+ }
+ }
+
+ private static void VarLoopI() {
+ for (int i = 0; i < sArrI.length; i++) {
+ sArrI[i] = sI;
+ if (i == 10)
+ sI++;
+ }
+ }
+
+ private static void VarLoopJ() {
+ for (int i = 0; i < sArrJ.length; i++) {
+ sArrJ[i] = sJ;
+ if (i == 10)
+ sJ++;
+ }
+ }
+
+ private static void VarLoopF() {
+ for (int i = 0; i < sArrF.length; i++) {
+ sArrF[i] = sF;
+ if (i == 10)
+ sF++;
+ }
+ }
+
+ private static void VarLoopD() {
+ for (int i = 0; i < sArrD.length; i++) {
+ sArrD[i] = sD;
+ if (i == 10)
+ sD++;
+ }
+ }
+
+ private static void VarLoopL() {
+ for (int i = 0; i < sArrL.length; i++) {
+ sArrL[i] = sL;
+ if (i == 10)
+ sL = anotherObject;
+ }
+ }
+
+ //
+ // Loops on static arrays with a cross-over reference.
+ // Incorrect hoisting is detected by incorrect outcome.
+ // In addition, the checker is used to detect no hoisting.
+ //
+
+ /// CHECK-START: void Main.CrossOverLoopZ() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopZ() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopZ() {
+ sArrZ[20] = false;
+ for (int i = 0; i < sArrZ.length; i++) {
+ sArrZ[i] = !sArrZ[20];
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopB() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopB() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopB() {
+ sArrB[20] = 11;
+ for (int i = 0; i < sArrB.length; i++) {
+ sArrB[i] = (byte)(sArrB[20] + 2);
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopC() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopC() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopC() {
+ sArrC[20] = 11;
+ for (int i = 0; i < sArrC.length; i++) {
+ sArrC[i] = (char)(sArrC[20] + 2);
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopS() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopS() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopS() {
+ sArrS[20] = 11;
+ for (int i = 0; i < sArrS.length; i++) {
+ sArrS[i] = (short)(sArrS[20] + 2);
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopI() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopI() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopI() {
+ sArrI[20] = 11;
+ for (int i = 0; i < sArrI.length; i++) {
+ sArrI[i] = sArrI[20] + 2;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopJ() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopJ() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopJ() {
+ sArrJ[20] = 11;
+ for (int i = 0; i < sArrJ.length; i++) {
+ sArrJ[i] = sArrJ[20] + 2;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopF() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopF() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopF() {
+ sArrF[20] = 11;
+ for (int i = 0; i < sArrF.length; i++) {
+ sArrF[i] = sArrF[20] + 2;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopD() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopD() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopD() {
+ sArrD[20] = 11;
+ for (int i = 0; i < sArrD.length; i++) {
+ sArrD[i] = sArrD[20] + 2;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoopL() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.CrossOverLoopL() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void CrossOverLoopL() {
+ sArrL[20] = anotherObject;
+ for (int i = 0; i < sArrL.length; i++) {
+ sArrL[i] = (sArrL[20] == anObject) ? anotherObject : anObject;
+ }
+ }
+
+ //
+ // False cross-over loops on static arrays with data types (I/F and J/D) that used
+ // to be aliased in an older version of the compiler. This alias has been removed,
+ // however, which enables hoisting the invariant array reference.
+ //
+
+ /// CHECK-START: void Main.FalseCrossOverLoop1() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop1() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void FalseCrossOverLoop1() {
+ sArrF[20] = -1;
+ for (int i = 0; i < sArrI.length; i++) {
+ sArrI[i] = (int) sArrF[20] - 2;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop2() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop2() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void FalseCrossOverLoop2() {
+ sArrI[20] = -2;
+ for (int i = 0; i < sArrF.length; i++) {
+ sArrF[i] = sArrI[20] - 2;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop3() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop3() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void FalseCrossOverLoop3() {
+ sArrD[20] = -3;
+ for (int i = 0; i < sArrJ.length; i++) {
+ sArrJ[i] = (long) sArrD[20] - 2;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop4() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop4() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private static void FalseCrossOverLoop4() {
+ sArrJ[20] = -4;
+ for (int i = 0; i < sArrD.length; i++) {
+ sArrD[i] = sArrJ[20] - 2;
+ }
+ }
+
+ //
+ // Main driver and testers.
+ //
+
+ public static void main(String[] args) {
+ DoStaticTests();
+ System.out.println("passed");
+ }
+
+ private static void DoStaticTests() {
+ // Type Z.
+ sZ = true;
+ sArrZ = new boolean[100];
+ InvLoopZ();
+ for (int i = 0; i < sArrZ.length; i++) {
+ expectEquals(true, sArrZ[i]);
+ }
+ VarLoopZ();
+ for (int i = 0; i < sArrZ.length; i++) {
+ expectEquals(i <= 10, sArrZ[i]);
+ }
+ CrossOverLoopZ();
+ for (int i = 0; i < sArrZ.length; i++) {
+ expectEquals(i <= 20, sArrZ[i]);
+ }
+ // Type B.
+ sB = 1;
+ sArrB = new byte[100];
+ InvLoopB();
+ for (int i = 0; i < sArrB.length; i++) {
+ expectEquals(1, sArrB[i]);
+ }
+ VarLoopB();
+ for (int i = 0; i < sArrB.length; i++) {
+ expectEquals(i <= 10 ? 1 : 2, sArrB[i]);
+ }
+ CrossOverLoopB();
+ for (int i = 0; i < sArrB.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrB[i]);
+ }
+ // Type C.
+ sC = 2;
+ sArrC = new char[100];
+ InvLoopC();
+ for (int i = 0; i < sArrC.length; i++) {
+ expectEquals(2, sArrC[i]);
+ }
+ VarLoopC();
+ for (int i = 0; i < sArrC.length; i++) {
+ expectEquals(i <= 10 ? 2 : 3, sArrC[i]);
+ }
+ CrossOverLoopC();
+ for (int i = 0; i < sArrC.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrC[i]);
+ }
+ // Type S.
+ sS = 3;
+ sArrS = new short[100];
+ InvLoopS();
+ for (int i = 0; i < sArrS.length; i++) {
+ expectEquals(3, sArrS[i]);
+ }
+ VarLoopS();
+ for (int i = 0; i < sArrS.length; i++) {
+ expectEquals(i <= 10 ? 3 : 4, sArrS[i]);
+ }
+ CrossOverLoopS();
+ for (int i = 0; i < sArrS.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrS[i]);
+ }
+ // Type I.
+ sI = 4;
+ sArrI = new int[100];
+ InvLoopI();
+ for (int i = 0; i < sArrI.length; i++) {
+ expectEquals(4, sArrI[i]);
+ }
+ VarLoopI();
+ for (int i = 0; i < sArrI.length; i++) {
+ expectEquals(i <= 10 ? 4 : 5, sArrI[i]);
+ }
+ CrossOverLoopI();
+ for (int i = 0; i < sArrI.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrI[i]);
+ }
+ // Type J.
+ sJ = 5;
+ sArrJ = new long[100];
+ InvLoopJ();
+ for (int i = 0; i < sArrJ.length; i++) {
+ expectEquals(5, sArrJ[i]);
+ }
+ VarLoopJ();
+ for (int i = 0; i < sArrJ.length; i++) {
+ expectEquals(i <= 10 ? 5 : 6, sArrJ[i]);
+ }
+ CrossOverLoopJ();
+ for (int i = 0; i < sArrJ.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrJ[i]);
+ }
+ // Type F.
+ sF = 6.0f;
+ sArrF = new float[100];
+ InvLoopF();
+ for (int i = 0; i < sArrF.length; i++) {
+ expectEquals(6, sArrF[i]);
+ }
+ VarLoopF();
+ for (int i = 0; i < sArrF.length; i++) {
+ expectEquals(i <= 10 ? 6 : 7, sArrF[i]);
+ }
+ CrossOverLoopF();
+ for (int i = 0; i < sArrF.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrF[i]);
+ }
+ // Type D.
+ sD = 7.0;
+ sArrD = new double[100];
+ InvLoopD();
+ for (int i = 0; i < sArrD.length; i++) {
+ expectEquals(7.0, sArrD[i]);
+ }
+ VarLoopD();
+ for (int i = 0; i < sArrD.length; i++) {
+ expectEquals(i <= 10 ? 7 : 8, sArrD[i]);
+ }
+ CrossOverLoopD();
+ for (int i = 0; i < sArrD.length; i++) {
+ expectEquals(i <= 20 ? 13 : 15, sArrD[i]);
+ }
+ // Type L.
+ sL = anObject;
+ sArrL = new Object[100];
+ InvLoopL();
+ for (int i = 0; i < sArrL.length; i++) {
+ expectEquals(anObject, sArrL[i]);
+ }
+ VarLoopL();
+ for (int i = 0; i < sArrL.length; i++) {
+ expectEquals(i <= 10 ? anObject : anotherObject, sArrL[i]);
+ }
+ CrossOverLoopL();
+ for (int i = 0; i < sArrL.length; i++) {
+ expectEquals(i <= 20 ? anObject : anotherObject, sArrL[i]);
+ }
+ // False cross-over.
+ FalseCrossOverLoop1();
+ for (int i = 0; i < sArrI.length; i++) {
+ expectEquals(-3, sArrI[i]);
+ }
+ FalseCrossOverLoop2();
+ for (int i = 0; i < sArrF.length; i++) {
+ expectEquals(-4, sArrF[i]);
+ }
+ FalseCrossOverLoop3();
+ for (int i = 0; i < sArrJ.length; i++) {
+ expectEquals(-5, sArrJ[i]);
+ }
+ FalseCrossOverLoop4();
+ for (int i = 0; i < sArrD.length; i++) {
+ expectEquals(-6, sArrD[i]);
+ }
+ }
+
+ private static void expectEquals(boolean expected, boolean result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(byte expected, byte result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(char expected, char result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(short expected, short result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(float expected, float result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(double expected, double result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(Object expected, Object result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/test/525-checker-arrays-fields2/expected.txt b/test/525-checker-arrays-fields2/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/525-checker-arrays-fields2/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/525-checker-arrays-fields2/info.txt b/test/525-checker-arrays-fields2/info.txt
new file mode 100644
index 0000000000..3464e540a6
--- /dev/null
+++ b/test/525-checker-arrays-fields2/info.txt
@@ -0,0 +1 @@
+Test on (in)variant instance field and array references in loops.
diff --git a/test/525-checker-arrays-and-fields/src/Main.java b/test/525-checker-arrays-fields2/src/Main.java
index a635a5157f..2aa40fcdc1 100644
--- a/test/525-checker-arrays-and-fields/src/Main.java
+++ b/test/525-checker-arrays-fields2/src/Main.java
@@ -15,7 +15,7 @@
*/
//
-// Test on (in)variant static and instance field and array references in loops.
+// Test on (in)variant instance field and array references in loops.
//
public class Main {
@@ -23,34 +23,6 @@ public class Main {
private static Object anotherObject = new Object();
//
- // Static fields.
- //
-
- private static boolean sZ;
- private static byte sB;
- private static char sC;
- private static short sS;
- private static int sI;
- private static long sJ;
- private static float sF;
- private static double sD;
- private static Object sL;
-
- //
- // Static arrays.
- //
-
- private static boolean[] sArrZ;
- private static byte[] sArrB;
- private static char[] sArrC;
- private static short[] sArrS;
- private static int[] sArrI;
- private static long[] sArrJ;
- private static float[] sArrF;
- private static double[] sArrD;
- private static Object[] sArrL;
-
- //
// Instance fields.
//
@@ -79,346 +51,6 @@ public class Main {
private Object[] mArrL;
//
- // Loops on static arrays with invariant static field references.
- // The checker is used to ensure hoisting occurred.
- //
-
- /// CHECK-START: void Main.SInvLoopZ() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopZ() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopZ() {
- for (int i = 0; i < sArrZ.length; i++) {
- sArrZ[i] = sZ;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopB() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopB() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopB() {
- for (int i = 0; i < sArrB.length; i++) {
- sArrB[i] = sB;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopC() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopC() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopC() {
- for (int i = 0; i < sArrC.length; i++) {
- sArrC[i] = sC;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopS() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopS() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopS() {
- for (int i = 0; i < sArrS.length; i++) {
- sArrS[i] = sS;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopI() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopI() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopI() {
- for (int i = 0; i < sArrI.length; i++) {
- sArrI[i] = sI;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopJ() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopJ() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopJ() {
- for (int i = 0; i < sArrJ.length; i++) {
- sArrJ[i] = sJ;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopF() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopF() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopF() {
- for (int i = 0; i < sArrF.length; i++) {
- sArrF[i] = sF;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopD() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopD() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopD() {
- for (int i = 0; i < sArrD.length; i++) {
- sArrD[i] = sD;
- }
- }
-
- /// CHECK-START: void Main.SInvLoopL() licm (before)
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
- /// CHECK-DAG: StaticFieldGet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SInvLoopL() licm (after)
- /// CHECK-DAG: StaticFieldGet loop:none
- /// CHECK-DAG: StaticFieldGet loop:none
-
- private static void SInvLoopL() {
- for (int i = 0; i < sArrL.length; i++) {
- sArrL[i] = sL;
- }
- }
-
- //
- // Loops on static arrays with variant static field references.
- // Incorrect hoisting is detected by incorrect outcome.
- //
-
- private static void SVarLoopZ() {
- for (int i = 0; i < sArrZ.length; i++) {
- sArrZ[i] = sZ;
- if (i == 10)
- sZ = !sZ;
- }
- }
-
- private static void SVarLoopB() {
- for (int i = 0; i < sArrB.length; i++) {
- sArrB[i] = sB;
- if (i == 10)
- sB++;
- }
- }
-
- private static void SVarLoopC() {
- for (int i = 0; i < sArrC.length; i++) {
- sArrC[i] = sC;
- if (i == 10)
- sC++;
- }
- }
-
- private static void SVarLoopS() {
- for (int i = 0; i < sArrS.length; i++) {
- sArrS[i] = sS;
- if (i == 10)
- sS++;
- }
- }
-
- private static void SVarLoopI() {
- for (int i = 0; i < sArrI.length; i++) {
- sArrI[i] = sI;
- if (i == 10)
- sI++;
- }
- }
-
- private static void SVarLoopJ() {
- for (int i = 0; i < sArrJ.length; i++) {
- sArrJ[i] = sJ;
- if (i == 10)
- sJ++;
- }
- }
-
- private static void SVarLoopF() {
- for (int i = 0; i < sArrF.length; i++) {
- sArrF[i] = sF;
- if (i == 10)
- sF++;
- }
- }
-
- private static void SVarLoopD() {
- for (int i = 0; i < sArrD.length; i++) {
- sArrD[i] = sD;
- if (i == 10)
- sD++;
- }
- }
-
- private static void SVarLoopL() {
- for (int i = 0; i < sArrL.length; i++) {
- sArrL[i] = sL;
- if (i == 10)
- sL = anotherObject;
- }
- }
-
- //
- // Loops on static arrays with a cross-over reference.
- // Incorrect hoisting is detected by incorrect outcome.
- // In addition, the checker is used to detect no hoisting.
- //
-
- /// CHECK-START: void Main.SCrossOverLoopZ() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopZ() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopZ() {
- for (int i = 0; i < sArrZ.length; i++) {
- sArrZ[i] = !sArrZ[20];
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopB() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopB() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopB() {
- for (int i = 0; i < sArrB.length; i++) {
- sArrB[i] = (byte)(sArrB[20] + 2);
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopC() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopC() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopC() {
- for (int i = 0; i < sArrC.length; i++) {
- sArrC[i] = (char)(sArrC[20] + 2);
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopS() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopS() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopS() {
- for (int i = 0; i < sArrS.length; i++) {
- sArrS[i] = (short)(sArrS[20] + 2);
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopI() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopI() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopI() {
- for (int i = 0; i < sArrI.length; i++) {
- sArrI[i] = sArrI[20] + 2;
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopJ() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopJ() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopJ() {
- for (int i = 0; i < sArrJ.length; i++) {
- sArrJ[i] = sArrJ[20] + 2;
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopF() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopF() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopF() {
- for (int i = 0; i < sArrF.length; i++) {
- sArrF[i] = sArrF[20] + 2;
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopD() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopD() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopD() {
- for (int i = 0; i < sArrD.length; i++) {
- sArrD[i] = sArrD[20] + 2;
- }
- }
-
- /// CHECK-START: void Main.SCrossOverLoopL() licm (before)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- /// CHECK-START: void Main.SCrossOverLoopL() licm (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: ArraySet loop:{{B\d+}}
-
- private static void SCrossOverLoopL() {
- for (int i = 0; i < sArrL.length; i++) {
- sArrL[i] = (sArrL[20] == anObject) ? anotherObject : anObject;
- }
- }
-
- //
// Loops on instance arrays with invariant instance field references.
// The checker is used to ensure hoisting occurred.
//
@@ -633,278 +265,241 @@ public class Main {
//
/// CHECK-START: void Main.CrossOverLoopZ() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopZ() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopZ() {
+ mArrZ[20] = false;
for (int i = 0; i < mArrZ.length; i++) {
mArrZ[i] = !mArrZ[20];
}
}
/// CHECK-START: void Main.CrossOverLoopB() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopB() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopB() {
+ mArrB[20] = 111;
for (int i = 0; i < mArrB.length; i++) {
mArrB[i] = (byte)(mArrB[20] + 2);
}
}
/// CHECK-START: void Main.CrossOverLoopC() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopC() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopC() {
+ mArrC[20] = 111;
for (int i = 0; i < mArrC.length; i++) {
mArrC[i] = (char)(mArrC[20] + 2);
}
}
/// CHECK-START: void Main.CrossOverLoopS() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopS() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopS() {
+ mArrS[20] = 111;
for (int i = 0; i < mArrS.length; i++) {
mArrS[i] = (short)(mArrS[20] + 2);
}
}
/// CHECK-START: void Main.CrossOverLoopI() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopI() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopI() {
+ mArrI[20] = 111;
for (int i = 0; i < mArrI.length; i++) {
mArrI[i] = mArrI[20] + 2;
}
}
/// CHECK-START: void Main.CrossOverLoopJ() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopJ() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopJ() {
+ mArrJ[20] = 111;
for (int i = 0; i < mArrJ.length; i++) {
mArrJ[i] = mArrJ[20] + 2;
}
}
/// CHECK-START: void Main.CrossOverLoopF() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopF() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopF() {
+ mArrF[20] = 111;
for (int i = 0; i < mArrF.length; i++) {
mArrF[i] = mArrF[20] + 2;
}
}
/// CHECK-START: void Main.CrossOverLoopD() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopD() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopD() {
+ mArrD[20] = 111;
for (int i = 0; i < mArrD.length; i++) {
mArrD[i] = mArrD[20] + 2;
}
}
/// CHECK-START: void Main.CrossOverLoopL() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
/// CHECK-START: void Main.CrossOverLoopL() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
/// CHECK-DAG: ArrayGet loop:{{B\d+}}
/// CHECK-DAG: ArraySet loop:{{B\d+}}
private void CrossOverLoopL() {
+ mArrL[20] = anotherObject;
for (int i = 0; i < mArrL.length; i++) {
mArrL[i] = (mArrL[20] == anObject) ? anotherObject : anObject;
}
}
//
- // Driver and testers.
+ // False cross-over loops on instance arrays with data types (I/F and J/D) that used
+ // to be aliased in an older version of the compiler. This alias has been removed,
+ // however, which enables hoisting the invariant array reference.
//
- public static void main(String[] args) {
- DoStaticTests();
- new Main().DoInstanceTests();
- }
+ /// CHECK-START: void Main.FalseCrossOverLoop1() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
- private static void DoStaticTests() {
- // Type Z.
- sZ = true;
- sArrZ = new boolean[100];
- SInvLoopZ();
- for (int i = 0; i < sArrZ.length; i++) {
- expectEquals(true, sArrZ[i]);
- }
- SVarLoopZ();
- for (int i = 0; i < sArrZ.length; i++) {
- expectEquals(i <= 10, sArrZ[i]);
- }
- SCrossOverLoopZ();
- for (int i = 0; i < sArrZ.length; i++) {
- expectEquals(i <= 20, sArrZ[i]);
- }
- // Type B.
- sB = 1;
- sArrB = new byte[100];
- SInvLoopB();
- for (int i = 0; i < sArrB.length; i++) {
- expectEquals(1, sArrB[i]);
- }
- SVarLoopB();
- for (int i = 0; i < sArrB.length; i++) {
- expectEquals(i <= 10 ? 1 : 2, sArrB[i]);
- }
- SCrossOverLoopB();
- for (int i = 0; i < sArrB.length; i++) {
- expectEquals(i <= 20 ? 4 : 6, sArrB[i]);
- }
- // Type C.
- sC = 2;
- sArrC = new char[100];
- SInvLoopC();
- for (int i = 0; i < sArrC.length; i++) {
- expectEquals(2, sArrC[i]);
- }
- SVarLoopC();
- for (int i = 0; i < sArrC.length; i++) {
- expectEquals(i <= 10 ? 2 : 3, sArrC[i]);
- }
- SCrossOverLoopC();
- for (int i = 0; i < sArrC.length; i++) {
- expectEquals(i <= 20 ? 5 : 7, sArrC[i]);
- }
- // Type S.
- sS = 3;
- sArrS = new short[100];
- SInvLoopS();
- for (int i = 0; i < sArrS.length; i++) {
- expectEquals(3, sArrS[i]);
- }
- SVarLoopS();
- for (int i = 0; i < sArrS.length; i++) {
- expectEquals(i <= 10 ? 3 : 4, sArrS[i]);
- }
- SCrossOverLoopS();
- for (int i = 0; i < sArrS.length; i++) {
- expectEquals(i <= 20 ? 6 : 8, sArrS[i]);
- }
- // Type I.
- sI = 4;
- sArrI = new int[100];
- SInvLoopI();
- for (int i = 0; i < sArrI.length; i++) {
- expectEquals(4, sArrI[i]);
- }
- SVarLoopI();
- for (int i = 0; i < sArrI.length; i++) {
- expectEquals(i <= 10 ? 4 : 5, sArrI[i]);
- }
- SCrossOverLoopI();
- for (int i = 0; i < sArrI.length; i++) {
- expectEquals(i <= 20 ? 7 : 9, sArrI[i]);
- }
- // Type J.
- sJ = 5;
- sArrJ = new long[100];
- SInvLoopJ();
- for (int i = 0; i < sArrJ.length; i++) {
- expectEquals(5, sArrJ[i]);
- }
- SVarLoopJ();
- for (int i = 0; i < sArrJ.length; i++) {
- expectEquals(i <= 10 ? 5 : 6, sArrJ[i]);
- }
- SCrossOverLoopJ();
- for (int i = 0; i < sArrJ.length; i++) {
- expectEquals(i <= 20 ? 8 : 10, sArrJ[i]);
- }
- // Type F.
- sF = 6.0f;
- sArrF = new float[100];
- SInvLoopF();
- for (int i = 0; i < sArrF.length; i++) {
- expectEquals(6, sArrF[i]);
- }
- SVarLoopF();
- for (int i = 0; i < sArrF.length; i++) {
- expectEquals(i <= 10 ? 6 : 7, sArrF[i]);
- }
- SCrossOverLoopF();
- for (int i = 0; i < sArrF.length; i++) {
- expectEquals(i <= 20 ? 9 : 11, sArrF[i]);
- }
- // Type D.
- sD = 7.0;
- sArrD = new double[100];
- SInvLoopD();
- for (int i = 0; i < sArrD.length; i++) {
- expectEquals(7.0, sArrD[i]);
- }
- SVarLoopD();
- for (int i = 0; i < sArrD.length; i++) {
- expectEquals(i <= 10 ? 7 : 8, sArrD[i]);
- }
- SCrossOverLoopD();
- for (int i = 0; i < sArrD.length; i++) {
- expectEquals(i <= 20 ? 10 : 12, sArrD[i]);
+ /// CHECK-START: void Main.FalseCrossOverLoop1() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private void FalseCrossOverLoop1() {
+ mArrF[20] = -1;
+ for (int i = 0; i < mArrI.length; i++) {
+ mArrI[i] = (int) mArrF[20] - 2;
}
- // Type L.
- sL = anObject;
- sArrL = new Object[100];
- SInvLoopL();
- for (int i = 0; i < sArrL.length; i++) {
- expectEquals(anObject, sArrL[i]);
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop2() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop2() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private void FalseCrossOverLoop2() {
+ mArrI[20] = -2;
+ for (int i = 0; i < mArrF.length; i++) {
+ mArrF[i] = mArrI[20] - 2;
}
- SVarLoopL();
- for (int i = 0; i < sArrL.length; i++) {
- expectEquals(i <= 10 ? anObject : anotherObject, sArrL[i]);
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop3() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop3() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private void FalseCrossOverLoop3() {
+ mArrD[20] = -3;
+ for (int i = 0; i < mArrJ.length; i++) {
+ mArrJ[i] = (long) mArrD[20] - 2;
}
- SCrossOverLoopL();
- for (int i = 0; i < sArrL.length; i++) {
- expectEquals(i <= 20 ? anObject : anotherObject, sArrL[i]);
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop4() licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ /// CHECK-START: void Main.FalseCrossOverLoop4() licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+
+ private void FalseCrossOverLoop4() {
+ mArrJ[20] = -4;
+ for (int i = 0; i < mArrD.length; i++) {
+ mArrD[i] = mArrJ[20] - 2;
}
}
+ //
+ // Main driver and testers.
+ //
+
+ public static void main(String[] args) {
+ new Main().DoInstanceTests();
+ System.out.println("passed");
+ }
+
private void DoInstanceTests() {
// Type Z.
mZ = true;
@@ -934,7 +529,7 @@ public class Main {
}
CrossOverLoopB();
for (int i = 0; i < mArrB.length; i++) {
- expectEquals(i <= 20 ? 4 : 6, mArrB[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrB[i]);
}
// Type C.
mC = 2;
@@ -949,7 +544,7 @@ public class Main {
}
CrossOverLoopC();
for (int i = 0; i < mArrC.length; i++) {
- expectEquals(i <= 20 ? 5 : 7, mArrC[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrC[i]);
}
// Type S.
mS = 3;
@@ -964,7 +559,7 @@ public class Main {
}
CrossOverLoopS();
for (int i = 0; i < mArrS.length; i++) {
- expectEquals(i <= 20 ? 6 : 8, mArrS[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrS[i]);
}
// Type I.
mI = 4;
@@ -979,7 +574,7 @@ public class Main {
}
CrossOverLoopI();
for (int i = 0; i < mArrI.length; i++) {
- expectEquals(i <= 20 ? 7 : 9, mArrI[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrI[i]);
}
// Type J.
mJ = 5;
@@ -994,7 +589,7 @@ public class Main {
}
CrossOverLoopJ();
for (int i = 0; i < mArrJ.length; i++) {
- expectEquals(i <= 20 ? 8 : 10, mArrJ[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrJ[i]);
}
// Type F.
mF = 6.0f;
@@ -1009,7 +604,7 @@ public class Main {
}
CrossOverLoopF();
for (int i = 0; i < mArrF.length; i++) {
- expectEquals(i <= 20 ? 9 : 11, mArrF[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrF[i]);
}
// Type D.
mD = 7.0;
@@ -1024,7 +619,7 @@ public class Main {
}
CrossOverLoopD();
for (int i = 0; i < mArrD.length; i++) {
- expectEquals(i <= 20 ? 10 : 12, mArrD[i]);
+ expectEquals(i <= 20 ? 113 : 115, mArrD[i]);
}
// Type L.
mL = anObject;
@@ -1041,6 +636,23 @@ public class Main {
for (int i = 0; i < mArrL.length; i++) {
expectEquals(i <= 20 ? anObject : anotherObject, mArrL[i]);
}
+ // False cross-over.
+ FalseCrossOverLoop1();
+ for (int i = 0; i < mArrI.length; i++) {
+ expectEquals(-3, mArrI[i]);
+ }
+ FalseCrossOverLoop2();
+ for (int i = 0; i < mArrF.length; i++) {
+ expectEquals(-4, mArrF[i]);
+ }
+ FalseCrossOverLoop3();
+ for (int i = 0; i < mArrJ.length; i++) {
+ expectEquals(-5, mArrJ[i]);
+ }
+ FalseCrossOverLoop4();
+ for (int i = 0; i < mArrD.length; i++) {
+ expectEquals(-6, mArrD[i]);
+ }
}
private static void expectEquals(boolean expected, boolean result) {
diff --git a/test/594-checker-array-alias/expected.txt b/test/594-checker-array-alias/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/594-checker-array-alias/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/594-checker-array-alias/info.txt b/test/594-checker-array-alias/info.txt
new file mode 100644
index 0000000000..57c6de541f
--- /dev/null
+++ b/test/594-checker-array-alias/info.txt
@@ -0,0 +1 @@
+Tests on array parameters with and without alias.
diff --git a/test/594-checker-array-alias/src/Main.java b/test/594-checker-array-alias/src/Main.java
new file mode 100644
index 0000000000..5ece2e295e
--- /dev/null
+++ b/test/594-checker-array-alias/src/Main.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+
+//
+// Test on array parameters with or without potential aliasing.
+//
+public class Main {
+
+ //
+ // Cross-over on parameters with potential aliasing on parameters.
+ // The arrays a and b may point to the same memory, which (without
+ // further runtime tests) prevents hoisting the seemingly invariant
+ // array reference.
+ //
+
+ /// CHECK-START: void Main.CrossOverLoop1(int[], int[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.CrossOverLoop1(int[], int[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void CrossOverLoop1(int a[], int b[]) {
+ b[20] = 99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoop2(float[], float[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.CrossOverLoop2(float[], float[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void CrossOverLoop2(float a[], float b[]) {
+ b[20] = 99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoop3(long[], long[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.CrossOverLoop3(long[], long[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void CrossOverLoop3(long a[], long b[]) {
+ b[20] = 99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.CrossOverLoop4(double[], double[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.CrossOverLoop4(double[], double[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void CrossOverLoop4(double a[], double b[]) {
+ b[20] = 99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ //
+ // False cross-over on parameters. Parameters have same width (which used to
+ // cause a false type aliasing in an older version of the compiler), but since
+ // the types are different cannot be aliased. Thus, the invariant array
+ // reference can be hoisted.
+ //
+
+ /// CHECK-START: void Main.FalseCrossOverLoop1(int[], float[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.FalseCrossOverLoop1(int[], float[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void FalseCrossOverLoop1(int a[], float b[]) {
+ b[20] = -99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = (int) b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop2(float[], int[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.FalseCrossOverLoop2(float[], int[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void FalseCrossOverLoop2(float a[], int b[]) {
+ b[20] = -99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop3(long[], double[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.FalseCrossOverLoop3(long[], double[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void FalseCrossOverLoop3(long a[], double b[]) {
+ b[20] = -99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = (long) b[20] - 7;
+ }
+ }
+
+ /// CHECK-START: void Main.FalseCrossOverLoop4(double[], long[]) licm (before)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ //
+ /// CHECK-START: void Main.FalseCrossOverLoop4(double[], long[]) licm (after)
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:{{B\d+}}
+ private static void FalseCrossOverLoop4(double a[], long b[]) {
+ b[20] = -99;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = b[20] - 7;
+ }
+ }
+
+ //
+ // Main driver and testers.
+ //
+
+ public static void main(String[] args) {
+ int[] aI = new int[100];
+ float[] aF = new float[100];
+ long[] aJ = new long[100];
+ double[] aD = new double[100];
+
+ // Type I.
+ CrossOverLoop1(aI, aI);
+ for (int i = 0; i < aI.length; i++) {
+ expectEquals(i <= 20 ? 92 : 85, aI[i]);
+ }
+ // Type F.
+ CrossOverLoop2(aF, aF);
+ for (int i = 0; i < aF.length; i++) {
+ expectEquals(i <= 20 ? 92 : 85, aF[i]);
+ }
+ // Type J.
+ CrossOverLoop3(aJ, aJ);
+ for (int i = 0; i < aJ.length; i++) {
+ expectEquals(i <= 20 ? 92 : 85, aJ[i]);
+ }
+ // Type D.
+ CrossOverLoop4(aD, aD);
+ for (int i = 0; i < aD.length; i++) {
+ expectEquals(i <= 20 ? 92 : 85, aD[i]);
+ }
+
+ // Type I vs F.
+ FalseCrossOverLoop1(aI, aF);
+ for (int i = 0; i < aI.length; i++) {
+ expectEquals(-106, aI[i]);
+ }
+ // Type F vs I.
+ FalseCrossOverLoop2(aF, aI);
+ for (int i = 0; i < aF.length; i++) {
+ expectEquals(-106, aF[i]);
+ }
+ // Type J vs D.
+ FalseCrossOverLoop3(aJ, aD);
+ for (int i = 0; i < aJ.length; i++) {
+ expectEquals(-106, aJ[i]);
+ }
+ // Type D vs J.
+ FalseCrossOverLoop4(aD, aJ);
+ for (int i = 0; i < aD.length; i++) {
+ expectEquals(-106, aD[i]);
+ }
+
+ // Real-world example where incorrect type assignment could introduce a bug.
+ // The library sorting algorithm is heavy on array reads and writes, and
+ // assigning the wrong J/D type to one of these would introduce errors.
+ for (int i = 0; i < aD.length; i++) {
+ aD[i] = aD.length - i - 1;
+ }
+ Arrays.sort(aD);
+ for (int i = 0; i < aD.length; i++) {
+ expectEquals((double) i, aD[i]);
+ }
+
+ System.out.println("passed");
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(float expected, float result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(double expected, double result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}