static bool IsAddOrSubAConstant(HInstruction* instruction,
/* out */ HInstruction** left_instruction,
/* out */ int32_t* right_constant) {
- if (instruction->IsAdd() || instruction->IsSub()) {
+ HInstruction* left_so_far = nullptr;
+ int32_t right_so_far = 0;
+ while (instruction->IsAdd() || instruction->IsSub()) {
HBinaryOperation* bin_op = instruction->AsBinaryOperation();
HInstruction* left = bin_op->GetLeft();
HInstruction* right = bin_op->GetRight();
if (right->IsIntConstant()) {
- *left_instruction = left;
- int32_t c = right->AsIntConstant()->GetValue();
- *right_constant = instruction->IsAdd() ? c : -c;
- return true;
+ int32_t v = right->AsIntConstant()->GetValue();
+ int32_t c = instruction->IsAdd() ? v : -v;
+ if (!WouldAddOverflowOrUnderflow(right_so_far, c)) {
+ instruction = left;
+ left_so_far = left;
+ right_so_far += c;
+ continue;
+ }
}
+ break;
}
- *left_instruction = nullptr;
- *right_constant = 0;
- return false;
+ // Return result: either false and "null+0" or true and "instr+constant".
+ *left_instruction = left_so_far;
+ *right_constant = right_so_far;
+ return left_so_far != nullptr;
}
// Expresses any instruction as a value bound.
array[base + 1] = 1;
}
+ /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (before)
+ /// CHECK: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK: BoundsCheck
+ /// CHECK: ArraySet
+
+ /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (after)
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArraySet
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArraySet
+
+ static void constantIndexing10(int[] array, int base) {
+ // Offset hidden in incremented base.
+ array[base] = 1;
+ array[++base] = 2;
+ array[++base] = 3;
+ array[++base] = 4;
+ }
+
static void runAllConstantIndices() {
int[] a1 = { 0 };
int[] a6 = { 0, 0, 0, 0, 0, 0 };
a6[3] != 3 || a6[4] != 40 || a6[5] != 10) {
System.out.println("constant indices 9 failed!");
}
+
+ constantIndexing10(a6, 0);
+ if (a6[0] != 1 || a6[1] != 2 || a6[2] != 3 ||
+ a6[3] != 4 || a6[4] != 40 || a6[5] != 10) {
+ System.out.println("constant indices 10 failed!");
+ }
}
// A helper into which the actual throwing function should be inlined.