diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 60 | ||||
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 72 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_riscv64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.h | 4 |
8 files changed, 57 insertions, 96 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index e8c94dd6b4..8f2f25355d 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -27,6 +27,7 @@ #include "base/scoped_arena_containers.h" #include "code_generator.h" #include "handle.h" +#include "intrinsics.h" #include "mirror/class.h" #include "nodes.h" #include "obj_ptr-inl.h" @@ -738,50 +739,21 @@ void GraphChecker::VisitInvoke(HInvoke* invoke) { // Check for intrinsics which should have been replaced by intermediate representation in the // instruction builder. - switch (invoke->GetIntrinsic()) { - case Intrinsics::kIntegerRotateRight: - case Intrinsics::kLongRotateRight: - case Intrinsics::kIntegerRotateLeft: - case Intrinsics::kLongRotateLeft: - case Intrinsics::kIntegerCompare: - case Intrinsics::kLongCompare: - case Intrinsics::kIntegerSignum: - case Intrinsics::kLongSignum: - case Intrinsics::kFloatIsNaN: - case Intrinsics::kDoubleIsNaN: - case Intrinsics::kStringIsEmpty: - case Intrinsics::kUnsafeLoadFence: - case Intrinsics::kUnsafeStoreFence: - case Intrinsics::kUnsafeFullFence: - case Intrinsics::kJdkUnsafeLoadFence: - case Intrinsics::kJdkUnsafeStoreFence: - case Intrinsics::kJdkUnsafeFullFence: - case Intrinsics::kVarHandleFullFence: - case Intrinsics::kVarHandleAcquireFence: - case Intrinsics::kVarHandleReleaseFence: - case Intrinsics::kVarHandleLoadLoadFence: - case Intrinsics::kVarHandleStoreStoreFence: - case Intrinsics::kMathMinIntInt: - case Intrinsics::kMathMinLongLong: - case Intrinsics::kMathMinFloatFloat: - case Intrinsics::kMathMinDoubleDouble: - case Intrinsics::kMathMaxIntInt: - case Intrinsics::kMathMaxLongLong: - case Intrinsics::kMathMaxFloatFloat: - case Intrinsics::kMathMaxDoubleDouble: - case Intrinsics::kMathAbsInt: - case Intrinsics::kMathAbsLong: - case Intrinsics::kMathAbsFloat: - case Intrinsics::kMathAbsDouble: - AddError( - StringPrintf("The graph contains an instrinsic which should have been replaced in the " - "instruction builder: %s:%d in block %d.", - invoke->DebugName(), - invoke->GetId(), - invoke->GetBlock()->GetBlockId())); - break; - default: - break; + if (IsIntrinsicWithSpecializedHir(invoke->GetIntrinsic()) && + // FIXME: The inliner can currently create graphs with any of the intrinsics with HIR. + // However, we are able to compensate for `StringCharAt` and `StringLength` in the + // `HInstructionSimplifier`, so we're allowing these two intrinsics for now, preserving + // the old behavior. Besides fixing the bug, we should also clean up the simplifier + // and remove `SimplifyStringCharAt` and `SimplifyStringLength`. Bug: 319045458 + invoke->GetIntrinsic() != Intrinsics::kStringCharAt && + invoke->GetIntrinsic() != Intrinsics::kStringLength) { + AddError( + StringPrintf("The graph contains the instrinsic %d which should have been replaced in the " + "instruction builder: %s:%d in block %d.", + enum_cast<int>(invoke->GetIntrinsic()), + invoke->DebugName(), + invoke->GetId(), + invoke->GetBlock()->GetBlockId())); } } diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 23d47c3857..ca0a8e81af 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -2009,6 +2009,7 @@ bool HInstructionBuilder::BuildSimpleIntrinsic(ArtMethod* method, break; default: // We do not have intermediate representation for other intrinsics. + DCHECK(!IsIntrinsicWithSpecializedHir(intrinsic)); return false; } DCHECK(instruction != nullptr); diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index d74d5d2a40..d14d264204 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -45,11 +45,23 @@ class IntrinsicVisitor : public ValueObject { switch (invoke->GetIntrinsic()) { case Intrinsics::kNone: return; + +#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \ + case Intrinsics::k ## Name: + ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR) +#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR + // Note: clang++ can optimize this `switch` to a range check and a virtual dispatch + // with indexed load from the vtable using an adjusted `invoke->GetIntrinsic()` + // as the index. However, a non-empty `case` causes clang++ to produce much worse + // code, so we want to limit this check to debug builds only. + DCHECK(false) << "Unexpected intrinsic with HIR: " << invoke->GetIntrinsic(); + return; + #define OPTIMIZING_INTRINSICS(Name, ...) \ case Intrinsics::k ## Name: \ Visit ## Name(invoke); \ return; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Do not put a default case. That way the compiler will complain if we missed a case. @@ -58,10 +70,10 @@ class IntrinsicVisitor : public ValueObject { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, ...) \ - virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) {} - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) -#undef OPTIMIZING_INTRINSICS +#define DECLARE_VISIT_INTRINSIC(Name, ...) \ + virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) = 0; + ART_INTRINSICS_WITH_HINVOKE_LIST(DECLARE_VISIT_INTRINSIC) +#undef DECLARE_VISIT_INTRINSIC static void MoveArguments(HInvoke* invoke, CodeGenerator* codegen, @@ -153,6 +165,18 @@ class IntrinsicVisitor : public ValueObject { DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); }; +static inline bool IsIntrinsicWithSpecializedHir(Intrinsics intrinsic) { + switch (intrinsic) { +#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \ + case Intrinsics::k ## Name: + ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR) +#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR + return true; + default: + return false; + } +} + #define GENERIC_OPTIMIZATION(name, bit) \ public: \ void Set##name() { SetBit(k##name); } \ @@ -278,44 +302,8 @@ void IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ << " should have been converted to HIR"; \ } #define UNREACHABLE_INTRINSICS(Arch) \ -UNREACHABLE_INTRINSIC(Arch, MathMinIntInt) \ -UNREACHABLE_INTRINSIC(Arch, MathMinLongLong) \ -UNREACHABLE_INTRINSIC(Arch, MathMinFloatFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathMinDoubleDouble) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxIntInt) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxLongLong) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxFloatFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxDoubleDouble) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsInt) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsLong) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsDouble) \ UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ -UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ -UNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ -UNREACHABLE_INTRINSIC(Arch, LongCompare) \ -UNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ -UNREACHABLE_INTRINSIC(Arch, LongSignum) \ -UNREACHABLE_INTRINSIC(Arch, StringCharAt) \ -UNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ -UNREACHABLE_INTRINSIC(Arch, StringLength) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeStoreFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeFullFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleFullFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence) +UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) template <typename IntrinsicLocationsBuilder, typename Codegenerator> bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h index 50e2e43f5f..d103cafdf7 100644 --- a/compiler/optimizing/intrinsics_arm64.h +++ b/compiler/optimizing/intrinsics_arm64.h @@ -48,7 +48,7 @@ class IntrinsicLocationsBuilderARM64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -71,7 +71,7 @@ class IntrinsicCodeGeneratorARM64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_arm_vixl.h b/compiler/optimizing/intrinsics_arm_vixl.h index fd86866d4e..7dcb52403b 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.h +++ b/compiler/optimizing/intrinsics_arm_vixl.h @@ -37,7 +37,7 @@ class IntrinsicLocationsBuilderARMVIXL final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -62,7 +62,7 @@ class IntrinsicCodeGeneratorARMVIXL final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_riscv64.h b/compiler/optimizing/intrinsics_riscv64.h index 8160c054ee..43068c04c2 100644 --- a/compiler/optimizing/intrinsics_riscv64.h +++ b/compiler/optimizing/intrinsics_riscv64.h @@ -42,7 +42,7 @@ class IntrinsicLocationsBuilderRISCV64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, ...) \ void Visit##Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -65,7 +65,7 @@ class IntrinsicCodeGeneratorRISCV64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, ...) \ void Visit##Name(HInvoke* invoke); - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h index 289a3c342c..565a92a11b 100644 --- a/compiler/optimizing/intrinsics_x86.h +++ b/compiler/optimizing/intrinsics_x86.h @@ -40,7 +40,7 @@ class IntrinsicLocationsBuilderX86 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -63,7 +63,7 @@ class IntrinsicCodeGeneratorX86 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h index 4a76c5c8ec..704fa9be0d 100644 --- a/compiler/optimizing/intrinsics_x86_64.h +++ b/compiler/optimizing/intrinsics_x86_64.h @@ -40,7 +40,7 @@ class IntrinsicLocationsBuilderX86_64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -63,7 +63,7 @@ class IntrinsicCodeGeneratorX86_64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: |