diff options
-rw-r--r-- | compiler/optimizing/code_generator.cc | 60 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips64.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier_shared.cc | 3 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 83 | ||||
-rw-r--r-- | compiler/optimizing/nodes_shared.h | 7 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_entrypoints_enum.cc | 51 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_entrypoints_enum.h | 1 | ||||
-rw-r--r-- | test/527-checker-array-access-split/src/Main.java | 64 |
14 files changed, 145 insertions, 140 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 6732670ffc..51ba187c1b 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -1179,37 +1179,51 @@ void CodeGenerator::EmitParallelMoves(Location from1, GetMoveResolver()->EmitNativeCode(¶llel_move); } -void CodeGenerator::ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path) { +void CodeGenerator::ValidateInvokeRuntime(QuickEntrypointEnum entrypoint, + HInstruction* instruction, + SlowPathCode* slow_path) { // Ensure that the call kind indication given to the register allocator is - // coherent with the runtime call generated, and that the GC side effect is - // set when required. + // coherent with the runtime call generated. if (slow_path == nullptr) { DCHECK(instruction->GetLocations()->WillCall()) << "instruction->DebugName()=" << instruction->DebugName(); - DCHECK(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC())) - << "instruction->DebugName()=" << instruction->DebugName() - << " instruction->GetSideEffects().ToString()=" << instruction->GetSideEffects().ToString(); } else { DCHECK(instruction->GetLocations()->CallsOnSlowPath() || slow_path->IsFatal()) << "instruction->DebugName()=" << instruction->DebugName() << " slow_path->GetDescription()=" << slow_path->GetDescription(); - DCHECK(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()) || - // When (non-Baker) read barriers are enabled, some instructions - // use a slow path to emit a read barrier, which does not trigger - // GC. - (kEmitCompilerReadBarrier && - !kUseBakerReadBarrier && - (instruction->IsInstanceFieldGet() || - instruction->IsStaticFieldGet() || - instruction->IsArrayGet() || - instruction->IsLoadClass() || - instruction->IsLoadString() || - instruction->IsInstanceOf() || - instruction->IsCheckCast() || - (instruction->IsInvokeVirtual() && instruction->GetLocations()->Intrinsified())))) - << "instruction->DebugName()=" << instruction->DebugName() - << " instruction->GetSideEffects().ToString()=" << instruction->GetSideEffects().ToString() - << " slow_path->GetDescription()=" << slow_path->GetDescription(); + } + + // Check that the GC side effect is set when required. + // TODO: Reverse EntrypointCanTriggerGC + if (EntrypointCanTriggerGC(entrypoint)) { + if (slow_path == nullptr) { + DCHECK(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC())) + << "instruction->DebugName()=" << instruction->DebugName() + << " instruction->GetSideEffects().ToString()=" + << instruction->GetSideEffects().ToString(); + } else { + DCHECK(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()) || + // When (non-Baker) read barriers are enabled, some instructions + // use a slow path to emit a read barrier, which does not trigger + // GC. + (kEmitCompilerReadBarrier && + !kUseBakerReadBarrier && + (instruction->IsInstanceFieldGet() || + instruction->IsStaticFieldGet() || + instruction->IsArrayGet() || + instruction->IsLoadClass() || + instruction->IsLoadString() || + instruction->IsInstanceOf() || + instruction->IsCheckCast() || + (instruction->IsInvokeVirtual() && instruction->GetLocations()->Intrinsified())))) + << "instruction->DebugName()=" << instruction->DebugName() + << " instruction->GetSideEffects().ToString()=" + << instruction->GetSideEffects().ToString() + << " slow_path->GetDescription()=" << slow_path->GetDescription(); + } + } else { + // The GC side effect is not required for the instruction. But the instruction might still have + // it, for example if it calls other entrypoints requiring it. } // Check the coherency of leaf information. diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index b4d4b9b760..22b5c9cff4 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -404,7 +404,9 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { // Perfoms checks pertaining to an InvokeRuntime call. - void ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path); + void ValidateInvokeRuntime(QuickEntrypointEnum entrypoint, + HInstruction* instruction, + SlowPathCode* slow_path); // Perfoms checks pertaining to an InvokeRuntimeWithoutRecordingPcInfo call. static void ValidateInvokeRuntimeWithoutRecordingPcInfo(HInstruction* instruction, diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 40c2b9c1ec..8b2d6fd838 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1177,7 +1177,7 @@ void CodeGeneratorARM::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); GenerateInvokeRuntime(GetThreadOffset<kArmPointerSize>(entrypoint).Int32Value()); if (EntrypointRequiresStackMap(entrypoint)) { RecordPcInfo(instruction, dex_pc, slow_path); diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 599185acd3..7f542da047 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1452,7 +1452,7 @@ void CodeGeneratorARM64::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); GenerateInvokeRuntime(GetThreadOffset<kArm64PointerSize>(entrypoint).Int32Value()); if (EntrypointRequiresStackMap(entrypoint)) { RecordPcInfo(instruction, dex_pc, slow_path); diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index b767aa5ef2..018cc457cc 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -1224,7 +1224,7 @@ void CodeGeneratorMIPS::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); bool reordering = __ SetReorder(false); __ LoadFromOffset(kLoadWord, T9, TR, GetThreadOffset<kMipsPointerSize>(entrypoint).Int32Value()); __ Jalr(T9); diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 4d87523206..557e5da916 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -946,7 +946,7 @@ void CodeGeneratorMIPS64::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); // TODO: anything related to T9/GP/GOT/PIC/.so's? __ LoadFromOffset(kLoadDoubleword, T9, diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 05182139bb..172ce4ab12 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -754,7 +754,7 @@ void CodeGeneratorX86::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); GenerateInvokeRuntime(GetThreadOffset<kX86PointerSize>(entrypoint).Int32Value()); if (EntrypointRequiresStackMap(entrypoint)) { RecordPcInfo(instruction, dex_pc, slow_path); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 506a7b1630..1943ddc6f7 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -981,7 +981,7 @@ void CodeGeneratorX86_64::InvokeRuntime(QuickEntrypointEnum entrypoint, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path) { - ValidateInvokeRuntime(instruction, slow_path); + ValidateInvokeRuntime(entrypoint, instruction, slow_path); GenerateInvokeRuntime(GetThreadOffset<kX86_64PointerSize>(entrypoint).Int32Value()); if (EntrypointRequiresStackMap(entrypoint)) { RecordPcInfo(instruction, dex_pc, slow_path); diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc index 8f7778fe68..04e063c92e 100644 --- a/compiler/optimizing/instruction_simplifier_shared.cc +++ b/compiler/optimizing/instruction_simplifier_shared.cc @@ -259,7 +259,8 @@ bool TryExtractArrayAccessAddress(HInstruction* access, HIntConstant* offset = graph->GetIntConstant(data_offset); HIntermediateAddress* address = new (arena) HIntermediateAddress(array, offset, kNoDexPc); - address->SetReferenceTypeInfo(array->GetReferenceTypeInfo()); + // TODO: Is it ok to not have this on the intermediate address? + // address->SetReferenceTypeInfo(array->GetReferenceTypeInfo()); access->GetBlock()->InsertInstructionBefore(address, access); access->ReplaceInput(address, 0); // Both instructions must depend on GC to prevent any instruction that can diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index caecc578c6..6d207765e3 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -4374,7 +4374,7 @@ class HDiv FINAL : public HBinaryOperation { HInstruction* left, HInstruction* right, uint32_t dex_pc) - : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {} + : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {} template <typename T> T ComputeIntegral(T x, T y) const { @@ -4409,11 +4409,6 @@ class HDiv FINAL : public HBinaryOperation { ComputeFP(x->GetValue(), y->GetValue()), GetDexPc()); } - static SideEffects SideEffectsForArchRuntimeCalls() { - // The generated code can use a runtime call. - return SideEffects::CanTriggerGC(); - } - DECLARE_INSTRUCTION(Div); private: @@ -4426,7 +4421,7 @@ class HRem FINAL : public HBinaryOperation { HInstruction* left, HInstruction* right, uint32_t dex_pc) - : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {} + : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {} template <typename T> T ComputeIntegral(T x, T y) const { @@ -4461,10 +4456,6 @@ class HRem FINAL : public HBinaryOperation { ComputeFP(x->GetValue(), y->GetValue()), GetDexPc()); } - static SideEffects SideEffectsForArchRuntimeCalls() { - return SideEffects::CanTriggerGC(); - } - DECLARE_INSTRUCTION(Rem); private: @@ -4917,9 +4908,7 @@ class HTypeConversion FINAL : public HExpression<1> { public: // Instantiate a type conversion of `input` to `result_type`. HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc) - : HExpression(result_type, - SideEffectsForArchRuntimeCalls(input->GetType(), result_type), - dex_pc) { + : HExpression(result_type, SideEffects::None(), dex_pc) { SetRawInputAt(0, input); // Invariant: We should never generate a conversion to a Boolean value. DCHECK_NE(Primitive::kPrimBoolean, result_type); @@ -4938,18 +4927,6 @@ class HTypeConversion FINAL : public HExpression<1> { // containing the result. If the input cannot be converted, return nullptr. HConstant* TryStaticEvaluation() const; - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type input_type, - Primitive::Type result_type) { - // Some architectures may not require the 'GC' side effects, but at this point - // in the compilation process we do not know what architecture we will - // generate code for, so we must be conservative. - if ((Primitive::IsFloatingPointType(input_type) && Primitive::IsIntegralType(result_type)) - || (input_type == Primitive::kPrimLong && Primitive::IsFloatingPointType(result_type))) { - return SideEffects::CanTriggerGC(); - } - return SideEffects::None(); - } - DECLARE_INSTRUCTION(TypeConversion); private: @@ -5031,9 +5008,7 @@ class HInstanceFieldGet FINAL : public HExpression<1> { const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) - : HExpression(field_type, - SideEffectsForArchRuntimeCalls(field_type, is_volatile), - dex_pc), + : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc), field_info_(field_offset, field_type, is_volatile, @@ -5064,16 +5039,6 @@ class HInstanceFieldGet FINAL : public HExpression<1> { Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) { - SideEffects side_effects = SideEffects::FieldReadOfType(field_type, is_volatile); - - // MIPS delegates volatile kPrimLong and kPrimDouble loads to a runtime helper. - if (Primitive::Is64BitType(field_type)) { - side_effects.Add(SideEffects::CanTriggerGC()); - } - return side_effects; - } - DECLARE_INSTRUCTION(InstanceFieldGet); private: @@ -5094,8 +5059,7 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> { const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) - : HTemplateInstruction(SideEffectsForArchRuntimeCalls(field_type, is_volatile), - dex_pc), + : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc), field_info_(field_offset, field_type, is_volatile, @@ -5120,16 +5084,6 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> { bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); } void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) { - SideEffects side_effects = SideEffects::FieldWriteOfType(field_type, is_volatile); - - // MIPS delegates volatile kPrimLong and kPrimDouble stores to a runtime helper. - if (Primitive::Is64BitType(field_type)) { - side_effects.Add(SideEffects::CanTriggerGC()); - } - return side_effects; - } - DECLARE_INSTRUCTION(InstanceFieldSet); private: @@ -5934,9 +5888,7 @@ class HStaticFieldGet FINAL : public HExpression<1> { const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) - : HExpression(field_type, - SideEffectsForArchRuntimeCalls(field_type, is_volatile), - dex_pc), + : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc), field_info_(field_offset, field_type, is_volatile, @@ -5964,16 +5916,6 @@ class HStaticFieldGet FINAL : public HExpression<1> { Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) { - SideEffects side_effects = SideEffects::FieldReadOfType(field_type, is_volatile); - - // MIPS delegates volatile kPrimLong and kPrimDouble loads to a runtime helper. - if (Primitive::Is64BitType(field_type)) { - side_effects.Add(SideEffects::CanTriggerGC()); - } - return side_effects; - } - DECLARE_INSTRUCTION(StaticFieldGet); private: @@ -5994,8 +5936,7 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) - : HTemplateInstruction(SideEffectsForArchRuntimeCalls(field_type, is_volatile), - dex_pc), + : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc), field_info_(field_offset, field_type, is_volatile, @@ -6017,16 +5958,6 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); } void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) { - SideEffects side_effects = SideEffects::FieldWriteOfType(field_type, is_volatile); - - // MIPS delegates volatile kPrimLong and kPrimDouble stores to a runtime helper. - if (Primitive::Is64BitType(field_type)) { - side_effects.Add(SideEffects::CanTriggerGC()); - } - return side_effects; - } - DECLARE_INSTRUCTION(StaticFieldSet); private: diff --git a/compiler/optimizing/nodes_shared.h b/compiler/optimizing/nodes_shared.h index 8bd8667f84..73085f80b4 100644 --- a/compiler/optimizing/nodes_shared.h +++ b/compiler/optimizing/nodes_shared.h @@ -117,10 +117,15 @@ class HBitwiseNegatedRight FINAL : public HBinaryOperation { // This instruction computes an intermediate address pointing in the 'middle' of an object. The // result pointer cannot be handled by GC, so extra care is taken to make sure that this value is // never used across anything that can trigger GC. +// The result of this instruction is not a pointer in the sense of `Primitive::kPrimNot`. So we +// represent it by the type `Primitive::kPrimInt`. class HIntermediateAddress FINAL : public HExpression<2> { public: HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc) - : HExpression(Primitive::kPrimNot, SideEffects::DependsOnGC(), dex_pc) { + : HExpression(Primitive::kPrimInt, SideEffects::DependsOnGC(), dex_pc) { + DCHECK_EQ(Primitive::ComponentSize(Primitive::kPrimInt), + Primitive::ComponentSize(Primitive::kPrimNot)) + << "kPrimInt and kPrimNot have different sizes."; SetRawInputAt(0, base_address); SetRawInputAt(1, offset); } diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.cc b/runtime/entrypoints/quick/quick_entrypoints_enum.cc index 7b80af6477..81f152b6fd 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_enum.cc +++ b/runtime/entrypoints/quick/quick_entrypoints_enum.cc @@ -71,4 +71,55 @@ bool EntrypointRequiresStackMap(QuickEntrypointEnum trampoline) { } } +bool EntrypointCanTriggerGC(QuickEntrypointEnum entrypoint) { + switch (entrypoint) { + // Listed in the same order as in quick_entrypoints_list.h. + case kQuickCmpgDouble: + case kQuickCmpgFloat: + case kQuickCmplDouble: + case kQuickCmplFloat: + case kQuickCos: + case kQuickSin: + case kQuickAcos: + case kQuickAsin: + case kQuickAtan: + case kQuickAtan2: + case kQuickCbrt: + case kQuickCosh: + case kQuickExp: + case kQuickExpm1: + case kQuickHypot: + case kQuickLog: + case kQuickLog10: + case kQuickNextAfter: + case kQuickSinh: + case kQuickTan: + case kQuickTanh: + case kQuickFmod: + case kQuickL2d: + case kQuickFmodf: + case kQuickL2f: + case kQuickD2iz: + case kQuickF2iz: + case kQuickIdivmod: + case kQuickD2l: + case kQuickF2l: + case kQuickLdiv: + case kQuickLmod: + case kQuickLmul: + case kQuickShlLong: + case kQuickShrLong: + case kQuickUshrLong: + return false; + + /* Used by mips for 64bit volatile load/stores. */ + case kQuickA64Load: + case kQuickA64Store: + return false; + + default: + return true; + } +} + } // namespace art diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.h b/runtime/entrypoints/quick/quick_entrypoints_enum.h index 7674873731..abf2c34744 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_enum.h +++ b/runtime/entrypoints/quick/quick_entrypoints_enum.h @@ -63,6 +63,7 @@ template <> inline void CheckEntrypointTypes<kQuick ## name, __VA_ARGS__>() {}; #undef ENTRYPOINT_ENUM bool EntrypointRequiresStackMap(QuickEntrypointEnum trampoline); +bool EntrypointCanTriggerGC(QuickEntrypointEnum entrypoint); } // namespace art diff --git a/test/527-checker-array-access-split/src/Main.java b/test/527-checker-array-access-split/src/Main.java index 9435ef1def..3de900a3a9 100644 --- a/test/527-checker-array-access-split/src/Main.java +++ b/test/527-checker-array-access-split/src/Main.java @@ -101,7 +101,7 @@ public class Main { /// CHECK: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArrayGet [<<Address>>,<<Index>>] @@ -114,7 +114,7 @@ public class Main { /// CHECK: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArrayGet [<<Address>>,<<Index>>] public static int get(int array[], int index) { @@ -140,7 +140,7 @@ public class Main { /// CHECK: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address>>,<<Index>>,<<Arg>>] @@ -159,7 +159,7 @@ public class Main { /// CHECK: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address>>,<<Index>>,<<Arg>>] public static void set(int array[], int index, int value) { @@ -183,10 +183,10 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM64: void Main.getSet(int[], int) GVN$after_arch (after) @@ -194,7 +194,7 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK-NOT: IntermediateAddress @@ -214,10 +214,10 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM: void Main.getSet(int[], int) GVN$after_arch (after) @@ -225,7 +225,7 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK-NOT: IntermediateAddress @@ -253,11 +253,11 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK: NewArray - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) GVN$after_arch (after) @@ -265,11 +265,11 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK: NewArray - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: ArraySet [<<Address2>>,<<Index>>,<<Add>>] @@ -287,11 +287,11 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK: NewArray - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM: int[] Main.accrossGC(int[], int) GVN$after_arch (after) @@ -299,11 +299,11 @@ public class Main { /// CHECK-DAG: <<DataOffset:i\d+>> IntConstant /// CHECK: <<Array:l\d+>> NullCheck /// CHECK: <<Index:i\d+>> BoundsCheck - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK: NewArray - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: ArraySet [<<Address2>>,<<Index>>,<<Add>>] public static int[] accrossGC(int array[], int index) { @@ -343,10 +343,10 @@ public class Main { /// CHECK: <<Index:i\d+>> Phi /// CHECK: If // -------------- Loop - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() GVN$after_arch (after) @@ -356,7 +356,7 @@ public class Main { /// CHECK: <<Index:i\d+>> Phi /// CHECK: If // -------------- Loop - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK-NOT: IntermediateAddress @@ -380,10 +380,10 @@ public class Main { /// CHECK: <<Index:i\d+>> Phi /// CHECK: If // -------------- Loop - /// CHECK: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: <<ArrayGet:i\d+>> ArrayGet [<<Address1>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] - /// CHECK: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-NEXT: ArraySet [<<Address2>>,<<Index>>,<<Add>>] /// CHECK-START-ARM: int Main.canMergeAfterBCE1() GVN$after_arch (after) @@ -393,7 +393,7 @@ public class Main { /// CHECK: <<Index:i\d+>> Phi /// CHECK: If // -------------- Loop - /// CHECK: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: <<ArrayGet:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGet>>,<<Const1>>] /// CHECK-NOT: IntermediateAddress @@ -437,12 +437,12 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <<Index1:i\d+>> Add [<<Index>>,<<Const1>>] - /// CHECK-DAG: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI:i\d+>> ArrayGet [<<Address1>>,<<Index>>] - /// CHECK-DAG: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI1:i\d+>> ArrayGet [<<Address2>>,<<Index1>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGetI>>,<<ArrayGetI1>>] - /// CHECK: <<Address3:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address3:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: ArraySet [<<Address3>>,<<Index1>>,<<Add>>] /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN$after_arch (after) @@ -453,7 +453,7 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <<Index1:i\d+>> Add [<<Index>>,<<Const1>>] - /// CHECK-DAG: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK-DAG: <<ArrayGetI1:i\d+>> ArrayGet [<<Address>>,<<Index1>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGetI>>,<<ArrayGetI1>>] @@ -486,12 +486,12 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <<Index1:i\d+>> Add [<<Index>>,<<Const1>>] - /// CHECK-DAG: <<Address1:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address1:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI:i\d+>> ArrayGet [<<Address1>>,<<Index>>] - /// CHECK-DAG: <<Address2:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address2:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI1:i\d+>> ArrayGet [<<Address2>>,<<Index1>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGetI>>,<<ArrayGetI1>>] - /// CHECK: <<Address3:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK: <<Address3:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK: ArraySet [<<Address3>>,<<Index1>>,<<Add>>] /// CHECK-START-ARM: int Main.canMergeAfterBCE2() GVN$after_arch (after) @@ -502,7 +502,7 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <<Index1:i\d+>> Add [<<Index>>,<<Const1>>] - /// CHECK-DAG: <<Address:l\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] + /// CHECK-DAG: <<Address:i\d+>> IntermediateAddress [<<Array>>,<<DataOffset>>] /// CHECK-DAG: <<ArrayGetI:i\d+>> ArrayGet [<<Address>>,<<Index>>] /// CHECK-DAG: <<ArrayGetI1:i\d+>> ArrayGet [<<Address>>,<<Index1>>] /// CHECK: <<Add:i\d+>> Add [<<ArrayGetI>>,<<ArrayGetI1>>] |