diff options
author | 2017-05-05 14:07:29 -0700 | |
---|---|---|
committer | 2017-05-09 10:41:39 -0700 | |
commit | 50e20d54670aecf1a4fdcf37ef1606d5ca990559 (patch) | |
tree | cb61312693cd392c3f9a569153a55c3eef936714 | |
parent | e22445fba0e5747ea787429ac64577a9a62aded3 (diff) |
Moved knowledge on masking shift operands to simplifier.
Rationale:
It is better to have a single place that simplifies shift
factors outside the 32-bit or 64-bit distance range, so
that other phases (induction variable analysis, loop optimizations,
etc.) do not have to know about that.
Test: test-art-target, test-art-host
Change-Id: Idfd90259cca085426cc3055eccb90f3c0976036b
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/loop_optimization.cc | 21 | ||||
-rw-r--r-- | test/551-checker-shifter-operand/src/Main.java | 131 | ||||
-rw-r--r-- | test/640-checker-int-simd/src/Main.java | 79 | ||||
-rw-r--r-- | test/640-checker-long-simd/src/Main.java | 79 |
5 files changed, 290 insertions, 34 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 2dcc12e294..2cedde900e 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -257,7 +257,8 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { if (shift_amount->IsConstant()) { int64_t cst = Int64FromConstant(shift_amount->AsConstant()); - if ((cst & implicit_mask) == 0) { + int64_t masked_cst = cst & implicit_mask; + if (masked_cst == 0) { // Replace code looking like // SHL dst, value, 0 // with @@ -266,6 +267,17 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { instruction->GetBlock()->RemoveInstruction(instruction); RecordSimplification(); return; + } else if (masked_cst != cst) { + // Replace code looking like + // SHL dst, value, cst + // where cst exceeds maximum distance with the equivalent + // SHL dst, value, cst & implicit_mask + // (as defined by shift semantics). This ensures other + // optimizations do not need to special case for such situations. + DCHECK_EQ(shift_amount->GetType(), Primitive::kPrimInt); + instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index */ 1); + RecordSimplification(); + return; } } diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index bbc55dd16f..881802d714 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -71,7 +71,7 @@ static bool IsSignExtensionAndGet(HInstruction* instruction, // extension when represented in the *width* of the given narrower data type // (the fact that char normally zero extends does not matter here). int64_t value = 0; - if (IsInt64AndGet(instruction, &value)) { + if (IsInt64AndGet(instruction, /*out*/ &value)) { switch (type) { case Primitive::kPrimByte: if (std::numeric_limits<int8_t>::min() <= value && @@ -119,7 +119,7 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, // extension when represented in the *width* of the given narrower data type // (the fact that byte/short normally sign extend does not matter here). int64_t value = 0; - if (IsInt64AndGet(instruction, &value)) { + if (IsInt64AndGet(instruction, /*out*/ &value)) { switch (type) { case Primitive::kPrimByte: if (std::numeric_limits<uint8_t>::min() <= value && @@ -833,19 +833,14 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, // TODO: accept symbolic, albeit loop invariant shift factors. HInstruction* opa = instruction->InputAt(0); HInstruction* opb = instruction->InputAt(1); - int64_t value = 0; - if (VectorizeUse(node, opa, generate_code, type, restrictions) && IsInt64AndGet(opb, &value)) { - // Make sure shift distance only looks at lower bits, as defined for sequential shifts. - int64_t mask = (instruction->GetType() == Primitive::kPrimLong) - ? kMaxLongShiftDistance - : kMaxIntShiftDistance; - int64_t distance = value & mask; + int64_t distance = 0; + if (VectorizeUse(node, opa, generate_code, type, restrictions) && + IsInt64AndGet(opb, /*out*/ &distance)) { // Restrict shift distance to packed data type width. int64_t max_distance = Primitive::ComponentSize(type) * 8; if (0 <= distance && distance < max_distance) { if (generate_code) { - HInstruction* s = graph_->GetIntConstant(distance); - GenerateVecOp(instruction, vector_map_->Get(opa), s, type); + GenerateVecOp(instruction, vector_map_->Get(opa), opb, type); } return true; } @@ -1177,14 +1172,14 @@ bool HLoopOptimization::VectorizeHalvingAddIdiom(LoopNode* node, int64_t value = 0; if ((instruction->IsShr() || instruction->IsUShr()) && - IsInt64AndGet(instruction->InputAt(1), &value) && value == 1) { + IsInt64AndGet(instruction->InputAt(1), /*out*/ &value) && value == 1) { // // TODO: make following code less sensitive to associativity and commutativity differences. // HInstruction* x = instruction->InputAt(0); // Test for an optional rounding part (x + 1) >> 1. bool is_rounded = false; - if (x->IsAdd() && IsInt64AndGet(x->InputAt(1), &value) && value == 1) { + if (x->IsAdd() && IsInt64AndGet(x->InputAt(1), /*out*/ &value) && value == 1) { x = x->InputAt(0); is_rounded = true; } diff --git a/test/551-checker-shifter-operand/src/Main.java b/test/551-checker-shifter-operand/src/Main.java index e9673987da..bf09a6aa5e 100644 --- a/test/551-checker-shifter-operand/src/Main.java +++ b/test/551-checker-shifter-operand/src/Main.java @@ -642,6 +642,123 @@ public class Main { // Each test line below should see one merge. + // + /// CHECK-START: void Main.$opt$validateShiftInt(int, int) instruction_simplifier$after_inlining (before) + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK-NOT: Shl + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK-NOT: Shl + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK-NOT: UShr + // + // Note: simplification after inlining removes `b << 32`, `b >> 32` and `b >>> 32`. + // + /// CHECK-START: void Main.$opt$validateShiftInt(int, int) instruction_simplifier$after_inlining (after) + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK-NOT: Shl + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK-NOT: Shl + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK-NOT: UShr + // + // Note: simplification followed by GVN exposes the common subexpressions between shifts with larger distance + // `b << 62`, `b << 63` etc. and the equivalent smaller distances. + // + /// CHECK-START: void Main.$opt$validateShiftInt(int, int) GVN (after) + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK: Shl + /// CHECK-NOT: Shl + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK: Shr + /// CHECK-NOT: Shl + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK: UShr + /// CHECK-NOT: UShr + // /// CHECK-START-ARM: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm (after) /// CHECK: DataProcWithShifterOp /// CHECK: DataProcWithShifterOp @@ -670,14 +787,7 @@ public class Main { /// CHECK: DataProcWithShifterOp /// CHECK: DataProcWithShifterOp /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp /// CHECK-NOT: DataProcWithShifterOp - // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier. /// CHECK-START-ARM: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm (after) /// CHECK-NOT: Shl @@ -712,14 +822,7 @@ public class Main { /// CHECK: DataProcWithShifterOp /// CHECK: DataProcWithShifterOp /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp - /// CHECK: DataProcWithShifterOp /// CHECK-NOT: DataProcWithShifterOp - // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier. /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after) /// CHECK-NOT: Shl diff --git a/test/640-checker-int-simd/src/Main.java b/test/640-checker-int-simd/src/Main.java index ba1e142668..97048eb951 100644 --- a/test/640-checker-int-simd/src/Main.java +++ b/test/640-checker-int-simd/src/Main.java @@ -76,6 +76,7 @@ public class Main { /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none // /// CHECK-START: void Main.div(int) loop_optimization (after) + /// CHECK-NOT: VecDiv // // Not supported on any architecture. // @@ -159,14 +160,81 @@ public class Main { // Shift sanity. // + // Expose constants to optimizing compiler, but not to front-end. + public static int $opt$inline$IntConstant32() { return 32; } + public static int $opt$inline$IntConstant33() { return 33; } + public static int $opt$inline$IntConstantMinus254() { return -254; } + + /// CHECK-START: void Main.shr32() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 32 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shr32() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shr32() loop_optimization (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Get>>] loop:<<Loop>> outer_loop:none static void shr32() { + // TODO: remove a[i] = a[i] altogether? for (int i = 0; i < 128; i++) - a[i] >>>= 32; // 0, since & 31 + a[i] >>>= $opt$inline$IntConstant32(); // 0, since & 31 } + /// CHECK-START: void Main.shr33() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 33 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shr33() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shr33() loop_optimization (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>> outer_loop:none static void shr33() { for (int i = 0; i < 128; i++) - a[i] >>>= 33; // 1, since & 31 + a[i] >>>= $opt$inline$IntConstant33(); // 1, since & 31 + } + + /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant -254 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shrMinus254() loop_optimization (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>> outer_loop:none + static void shrMinus254() { + for (int i = 0; i < 128; i++) + a[i] >>>= $opt$inline$IntConstantMinus254(); // 2, since & 31 } // @@ -240,9 +308,14 @@ public class Main { for (int i = 0; i < 128; i++) { expectEquals(0x1fffffff, a[i], "shr33"); } + shrMinus254(); + for (int i = 0; i < 128; i++) { + expectEquals(0x07ffffff, a[i], "shrMinus254"); + } + // Bit-wise not operator. not(); for (int i = 0; i < 128; i++) { - expectEquals(0xe0000000, a[i], "not"); + expectEquals(0xf8000000, a[i], "not"); } // Done. System.out.println("passed"); diff --git a/test/640-checker-long-simd/src/Main.java b/test/640-checker-long-simd/src/Main.java index 56411821f1..e42c716d19 100644 --- a/test/640-checker-long-simd/src/Main.java +++ b/test/640-checker-long-simd/src/Main.java @@ -74,6 +74,7 @@ public class Main { /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none // /// CHECK-START: void Main.div(long) loop_optimization (after) + /// CHECK-NOT: VecDiv // // Not supported on any architecture. // @@ -157,14 +158,81 @@ public class Main { // Shift sanity. // + // Expose constants to optimizing compiler, but not to front-end. + public static int $opt$inline$IntConstant64() { return 64; } + public static int $opt$inline$IntConstant65() { return 65; } + public static int $opt$inline$IntConstantMinus254() { return -254; } + + /// CHECK-START: void Main.shr64() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 64 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shr64() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shr64() loop_optimization (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Get>>] loop:<<Loop>> outer_loop:none static void shr64() { + // TODO: remove a[i] = a[i] altogether? for (int i = 0; i < 128; i++) - a[i] >>>= 64; // 0, since & 63 + a[i] >>>= $opt$inline$IntConstant64(); // 0, since & 63 } + /// CHECK-START: void Main.shr65() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 65 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shr65() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shr65() loop_optimization (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>> outer_loop:none static void shr65() { for (int i = 0; i < 128; i++) - a[i] >>>= 65; // 1, since & 63 + a[i] >>>= $opt$inline$IntConstant65(); // 1, since & 63 + } + + /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (before) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant -254 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.shrMinus254() loop_optimization (after) + /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>> outer_loop:none + static void shrMinus254() { + for (int i = 0; i < 128; i++) + a[i] >>>= $opt$inline$IntConstantMinus254(); // 2, since & 63 } // @@ -238,9 +306,14 @@ public class Main { for (int i = 0; i < 128; i++) { expectEquals(0x1fffffffffffffffL, a[i], "shr65"); } + shrMinus254(); + for (int i = 0; i < 128; i++) { + expectEquals(0x07ffffffffffffffL, a[i], "shrMinus254"); + } + // Bit-wise not operator. not(); for (int i = 0; i < 128; i++) { - expectEquals(0xe000000000000000L, a[i], "not"); + expectEquals(0xf800000000000000L, a[i], "not"); } // Done. System.out.println("passed"); |