r359960 - Reduce amount of work ODR hashing does.

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Sat May 4 09:05:58 PDT 2019


Does the ODR hashing have some sort of cycle breaking infrastructure -
so that if the same type is seen more than once (eg: classes have
members that have pointers back to the outer class type, etc) they
don't cause indefinite cycles? Should that infrastructure have caught
these cases & avoided the redundant work?

I'm curious to understand better how these things work/overlap/or don't.

On Fri, May 3, 2019 at 9:20 PM Richard Trieu via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
>
> Author: rtrieu
> Date: Fri May  3 21:22:33 2019
> New Revision: 359960
>
> URL: http://llvm.org/viewvc/llvm-project?rev=359960&view=rev
> Log:
> Reduce amount of work ODR hashing does.
>
> When a FunctionProtoType is in the original type in a DecayedType, the decayed
> type is a PointerType which points back the original FunctionProtoType.  The
> visitor for ODRHashing will attempt to process both Type's, doing double work.
> By chaining together multiple DecayedType's and FunctionProtoType's, this would
> result in 2^N Type's visited only N DecayedType's and N FunctionProtoType's
> exsit.  Another bug where VisitDecayedType and VisitAdjustedType did
> redundant work doubled the work at each level, giving 4^N Type's visited.  This
> patch removed the double work and detects when a FunctionProtoType decays to
> itself to only check the Type once.  This lowers the exponential runtime to
> linear runtime.  Fixes https://bugs.llvm.org/show_bug.cgi?id=41625
>
> Modified:
>     cfe/trunk/lib/AST/ODRHash.cpp
>     cfe/trunk/test/Modules/odr_hash.cpp
>
> Modified: cfe/trunk/lib/AST/ODRHash.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=359960&r1=359959&r2=359960&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ODRHash.cpp (original)
> +++ cfe/trunk/lib/AST/ODRHash.cpp Fri May  3 21:22:33 2019
> @@ -703,14 +703,36 @@ public:
>    void VisitType(const Type *T) {}
>
>    void VisitAdjustedType(const AdjustedType *T) {
> -    AddQualType(T->getOriginalType());
> -    AddQualType(T->getAdjustedType());
> +    QualType Original = T->getOriginalType();
> +    QualType Adjusted = T->getAdjustedType();
> +
> +    // The original type and pointee type can be the same, as in the case of
> +    // function pointers decaying to themselves.  Set a bool and only process
> +    // the type once, to prevent doubling the work.
> +    SplitQualType split = Adjusted.split();
> +    if (auto Pointer = dyn_cast<PointerType>(split.Ty)) {
> +      if (Pointer->getPointeeType() == Original) {
> +        Hash.AddBoolean(true);
> +        ID.AddInteger(split.Quals.getAsOpaqueValue());
> +        AddQualType(Original);
> +        VisitType(T);
> +        return;
> +      }
> +    }
> +
> +    // The original type and pointee type are different, such as in the case
> +    // of a array decaying to an element pointer.  Set a bool to false and
> +    // process both types.
> +    Hash.AddBoolean(false);
> +    AddQualType(Original);
> +    AddQualType(Adjusted);
> +
>      VisitType(T);
>    }
>
>    void VisitDecayedType(const DecayedType *T) {
> -    AddQualType(T->getDecayedType());
> -    AddQualType(T->getPointeeType());
> +    // getDecayedType and getPointeeType are derived from getAdjustedType
> +    // and don't need to be separately processed.
>      VisitAdjustedType(T);
>    }
>
>
> Modified: cfe/trunk/test/Modules/odr_hash.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=359960&r1=359959&r2=359960&view=diff
> ==============================================================================
> --- cfe/trunk/test/Modules/odr_hash.cpp (original)
> +++ cfe/trunk/test/Modules/odr_hash.cpp Fri May  3 21:22:33 2019
> @@ -4587,6 +4587,43 @@ int num = bar();
>  #endif
>  }
>
> +namespace FunctionProtoTypeDecay {
> +#if defined(FIRST)
> +struct S1 {
> +  struct X {};
> +  using Y = X(X());
> +};
> +#elif defined(SECOND)
> +struct S1 {
> +  struct X {};
> +  using Y = X(X(X()));
> +};
> +#else
> +S1 s1;
> +// expected-error at first.h:* {{'FunctionProtoTypeDecay::S1::Y' from module 'FirstModule' is not present in definition of 'FunctionProtoTypeDecay::S1' in module 'SecondModule'}}
> +// expected-note at second.h:* {{declaration of 'Y' does not match}}
> +#endif
> +
> +#if defined(FIRST)
> +struct S2 {
> +  struct X {};
> +  using Y =
> +      X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
> +      X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
> +      X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
> +      X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
> +      ))))))))))))))))
> +      ))))))))))))))))
> +      ))))))))))))))))
> +      ))))))))))))))));
> +};
> +#elif defined(SECOND)
> +#else
> +S2 s2;
> +#endif
> +
> +}
> +
>  // Keep macros contained to one file.
>  #ifdef FIRST
>  #undef FIRST
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list