Chris Tetreault via llvm-dev
2020-May-21 21:22 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
John,> This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable.While I’m at a loss to find a documented policy, I recall this thread (http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) where this claim was made and not disputed. The expected real benefits to this change are: 1) The names now match the semantics 2) It is now statically impossible to accidentally get the fixed number of elements from a scalable vector and 3) It forces everybody to fix their broken code. If we provided stability guarantees to downstream and out-of-tree codebases, then I might not agree that 3 is a benefit, but my understanding is that we do not provide this guarantee.> … Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector.This code is all broken already. I don’t think supporting common misuse of APIs in a codebase that does not provide stability guarantees is something we should be doing.> The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowedI agree. Unfortunately it happened, and our choices are to fix it or accept the technical debt forever.> the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it.The burden of creating the generalization should be placed on those who need it, I agree. However, once the generalization is in place, the burden is on everybody to use it correctly. The reason I’ve undertaken this refactor is because I found myself playing whack-a-mole with people adding new broken code after the fact. The previous API was very easy to misuse, so I don’t blame those people.> Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures?Everywhere that VectorType::getNumElements() is being called, we are either changing the code to cast to FixedVectorType, or we are updating the code to handle scalable vectors correctly. If the call site does not have test coverage with scalable vectors, this test coverage is being added. Even for obviously correct transformations such as `VectorType::get(SomeTy, SomeVecTy->getNumElements())` -> `VectorType::get(SomeTy, SomeVecTy->getElementCount())`, I have been required in code review to provide test coverage. We are taking this seriously.> “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler.Various languages implemented on top of LLVM have various different pointer types. However, the LLVM IR language only has one pointer type. The LLVM IR language has two types of vectors, and I think it’s reasonable to model them as a class hierarchy in this manner. I’m not familiar with the clang::PointerType situation, so I cannot pass judgement on it. Thanks, Christopher Tetreault From: John McCall <rjmccall at apple.com> Sent: Thursday, May 21, 2020 1:47 PM To: Chris Tetreault <ctetreau at quicinc.com> Cc: llvm-dev at lists.llvm.org Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR On 21 May 2020, at 16:01, Chris Tetreault wrote: Hi John, I’d like to address some points in your message. Practically speaking, this is going to break every out-of-tree frontend, backend, or optimization pass that supports SIMD types. My understanding is that the policy in LLVM development is that we do not let considerations for downstream and out-of-tree codebases affect the pace of development. This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. The C++ API is explicitly unstable. I maintain a downstream fork of LLVM myself, so I know the pain that this is causing because I get to fix all the issues in my internal codebase. However, the fix for downstream codebases is very simple: Just find all the places where it says VectorType, and change it to say FixedVectorType. … by having the VectorType type semantically repurposed out from under them. The documented semantics of VectorType prior to my RFC were that it is a generalization of all vector types. The VectorType contains an ElementCount, which is a pair of (bool, unsigned). If the bool is true, then the return value of getNumElements() is the minimum number of vector elements. If the bool is false, then it is the actual number of elements. My RFC has not changed these semantics. It will eventually delete a function that has been pervasively misused throughout the codebase, but the semantics remain the same. You are proposing a semantic change to VectorType to have it specifically be a fixed width vector. Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed; it should always have used a different type. Honestly, I’m not convinced your abstract base type is even going to be very useful in practice vs. just having a getVectorElementType() accessor that checks for both and otherwise returns null. … a particular largely-vendor-specific extension … All SIMD vectors are vendor specific extensions. Just because most of the most popular architectures have them does not make this not true. AArch64 and RISC-V have scalable vectors, so it is not just one architecture. It is the responsibility of all developers to ensure that they use the types correctly. It would be nice if the obvious thing to do is the correct thing to do. I’m not saying that we shouldn’t support scalable vector types. I’m saying that the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. … it’s much better for code that does support both to explicitly opt in by checking for and handling the more general type … This is how it will work. I am in the process of fixing up call sites that make fixed width assumptions so that they use FixedVectorType. Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? Because scalable vector types impose some major restrictions that aren’t imposed on normal vectors, and the static type system isn’t going to catch most of them. I think that it is important to ensure that things have clear sensible names, and to clean up historical baggage when the opportunity presents. “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. You have resigned yourself to doing a lot of work in pursuit of something that I really don’t think is actually an improvement. John. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200521/91786c38/attachment.html>
John McCall via llvm-dev
2020-May-21 22:32 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
On 21 May 2020, at 17:22, Chris Tetreault wrote:> John, > >> This is not categorically true, no. When we make changes that require >> large-scale updates for downstream codebases, we do so because >> there’s a real expected benefit to it. For the most part, we do >> make some effort to keep existing source interfaces stable. > While I’m at a loss to find a documented policy, I recall this > thread > (http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) > where this claim was made and not disputed. The expected real benefits > to this change are: 1) The names now match the semantics 2) It is now > statically impossible to accidentally get the fixed number of elements > from a scalable vector and 3) It forces everybody to fix their broken > code. If we provided stability guarantees to downstream and > out-of-tree codebases, then I might not agree that 3 is a benefit, but > my understanding is that we do not provide this guarantee. > >> … Probably 99% of the code using VectorType semantically requires >> it to be a fixed-width vector. > > This code is all broken already. I don’t think supporting common > misuse of APIs in a codebase that does not provide stability > guarantees is something we should be doing. > >> The generalization of VectorType to scalable vector types was a >> representational shortcut that should never have been allowed > > I agree. Unfortunately it happened, and our choices are to fix it or > accept the technical debt forever.Perhaps this is part of the root of our disagreement. I consider scalable vector types to be an experimental/unstable feature, as many features are when they’re first added to the compiler. I have much lower standards for disrupting the early adopters of features like that; if scalable vectors need to be split out of `VectorType`, we should just do it. Analogously, when we upstream the pointer-authentication feature, we will be upstreaming a rather flawed representation that I definitely expect us to revise after the fact. That will be problematic for early adopters of LLVM’s pointer authentication support, but that’s totally acceptable. John.> >> the burden of generalization should usually fall on the people who >> need to use the generalization, and otherwise we should aim to keep >> APIs stable when there’s no harm to it. > > The burden of creating the generalization should be placed on those > who need it, I agree. However, once the generalization is in place, > the burden is on everybody to use it correctly. The reason I’ve > undertaken this refactor is because I found myself playing > whack-a-mole with people adding new broken code after the fact. The > previous API was very easy to misuse, so I don’t blame those people. > >> Are you actually auditing and testing them all to work for scalable >> vector types, or are you just fixing the obvious compile failures? > Everywhere that VectorType::getNumElements() is being called, we are > either changing the code to cast to FixedVectorType, or we are > updating the code to handle scalable vectors correctly. If the call > site does not have test coverage with scalable vectors, this test > coverage is being added. Even for obviously correct transformations > such as `VectorType::get(SomeTy, SomeVecTy->getNumElements())` -> > `VectorType::get(SomeTy, SomeVecTy->getElementCount())`, I have been > required in code review to provide test coverage. We are taking this > seriously. > >> “Vector” has a traditional and dominant meaning as a fixed-width >> SIMD type, and the fact that you’ve introduced a generalization >> doesn’t change that. Clang supports multiple kinds of pointer, but >> we still reserve clang::PointerType for C pointers instead of making >> it an abstract superclass, thus letting our sense of logic introduce >> a million bugs through accidental generalization throughout the >> compiler. > Various languages implemented on top of LLVM have various different > pointer types. However, the LLVM IR language only has one pointer > type. The LLVM IR language has two types of vectors, and I think > it’s reasonable to model them as a class hierarchy in this manner. > I’m not familiar with the clang::PointerType situation, so I cannot > pass judgement on it. > > Thanks, > Christopher Tetreault > > From: John McCall <rjmccall at apple.com> > Sent: Thursday, May 21, 2020 1:47 PM > To: Chris Tetreault <ctetreau at quicinc.com> > Cc: llvm-dev at lists.llvm.org > Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of > VectorType in the IR > > > On 21 May 2020, at 16:01, Chris Tetreault wrote: > > Hi John, > > I’d like to address some points in your message. > > Practically speaking, this is going to break every out-of-tree > frontend, backend, or optimization pass that supports SIMD types. > > My understanding is that the policy in LLVM development is that we do > not let considerations for downstream and out-of-tree codebases affect > the pace of development. > > This is not categorically true, no. When we make changes that require > large-scale updates for downstream codebases, we do so because > there’s a real expected benefit to it. For the most part, we do make > some effort to keep existing source interfaces stable. > > The C++ API is explicitly unstable. I maintain a downstream fork of > LLVM myself, so I know the pain that this is causing because I get to > fix all the issues in my internal codebase. However, the fix for > downstream codebases is very simple: Just find all the places where it > says VectorType, and change it to say FixedVectorType. > > … by having the VectorType type semantically repurposed out from > under them. > > The documented semantics of VectorType prior to my RFC were that it is > a generalization of all vector types. The VectorType contains an > ElementCount, which is a pair of (bool, unsigned). If the bool is > true, then the return value of getNumElements() is the minimum number > of vector elements. If the bool is false, then it is the actual number > of elements. My RFC has not changed these semantics. It will > eventually delete a function that has been pervasively misused > throughout the codebase, but the semantics remain the same. You are > proposing a semantic change to VectorType to have it specifically be a > fixed width vector. > > Probably 99% of the code using VectorType semantically requires it to > be a fixed-width vector. The generalization of VectorType to scalable > vector types was a representational shortcut that should never have > been allowed; it should always have used a different type. Honestly, > I’m not convinced your abstract base type is even going to be very > useful in practice vs. just having a getVectorElementType() accessor > that checks for both and otherwise returns null. > > … a particular largely-vendor-specific extension … > > All SIMD vectors are vendor specific extensions. Just because most of > the most popular architectures have them does not make this not true. > AArch64 and RISC-V have scalable vectors, so it is not just one > architecture. It is the responsibility of all developers to ensure > that they use the types correctly. It would be nice if the obvious > thing to do is the correct thing to do. > > I’m not saying that we shouldn’t support scalable vector types. > I’m saying that the burden of generalization should usually fall on > the people who need to use the generalization, and otherwise we should > aim to keep APIs stable when there’s no harm to it. > > … it’s much better for code that does support both to explicitly > opt in by checking for and handling the more general type … > > This is how it will work. I am in the process of fixing up call sites > that make fixed width assumptions so that they use FixedVectorType. > > Are you actually auditing and testing them all to work for scalable > vector types, or are you just fixing the obvious compile failures? > Because scalable vector types impose some major restrictions that > aren’t imposed on normal vectors, and the static type system isn’t > going to catch most of them. > > I think that it is important to ensure that things have clear sensible > names, and to clean up historical baggage when the opportunity > presents. > > “Vector” has a traditional and dominant meaning as a fixed-width > SIMD type, and the fact that you’ve introduced a generalization > doesn’t change that. Clang supports multiple kinds of pointer, but > we still reserve clang::PointerType for C pointers instead of making > it an abstract superclass, thus letting our sense of logic introduce a > million bugs through accidental generalization throughout the > compiler. > > You have resigned yourself to doing a lot of work in pursuit of > something that I really don’t think is actually an improvement. > > John.-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200521/1b9bf827/attachment.html>
Chris Tetreault via llvm-dev
2020-May-22 07:15 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
John, For the last several months, those of us working on the scalable vectors feature have been examining the codebase, identifying places where llvm::VectorType is used incorrectly, and fixing them. The fact is that there are many places where VectorType is correctly taken to be the generic “any vector” type. getNumElements may be being called, but it’s being called in accordance with the previously documented semantics. There are many places where it isn’t as well, and many people add new usages that are incorrect. This puts us in an unfortunate situation: if we were to take your proposal and have VectorType be the fixed width vector type, then all of this work is undone. Every place that has been fixed up to correctly have VectorType be used as a universal vector type will now incorrectly have the fixed width vector type being used as the universal vector type. Since VectorType will inherit from BaseVectorType, it will have inherited the getElementCount(), so the compiler will happily continue to compile this code. However, none of this code will even work with scalable vectors because the bool will always be false. There will be no compile time indication that this is going on, functions will just start mysteriously returning nullptr. Earlier this afternoon, I set about seeing how much work it would be to change the type names as you have suggested. I do not see any way forward other than painstakingly auditing the code. On the other hand, creating a new fixed width vector type has a clear upgrade path. 1) delete getNumElements() from the base class locally. 2) try to build 3) fix the failures, uploading patches for these fixes 4) once step 3 is completed throughout the codebase, merge the patch to remove getNumElements() from VectorType. Downstream and out-of-tree codebases have this upgrade path as well. There exists no easy upgrade path if we go the other way and have VectorType become a specifically fixed-width vector type. Basically, I believe that the best thing to do is to move forward with the type names that I have proposed: 1. The type names more accurately represent the usage of the types. 2. Changing course now would result in a tremendous amount of rework being done in the upstream codebase. This will have a significant impact on the pace of development in upstream. 3. The process for completing the changes would be much easier if we use the types I propose. The compiler can tell you if you’re using getNumElements() on a potentially scalable vector. The compiler cannot tell you that SomeFixedVector->getElementCount().Scalable and isa<ScalableVectorType>(SomeFixedVector) are always false. Additionally, for those who disagree that the LLVM developer policy is to disregard the needs of downstream codebases when making changes to upstream, I submit that not throwing away months of work by everybody working to fix the codebase to handle scalable vectors represents a real expected benefit. I personally have been spending most of my time on this since January. Thanks, Christopher Tetreault From: John McCall <rjmccall at apple.com> Sent: Thursday, May 21, 2020 3:32 PM To: Chris Tetreault <ctetreau at quicinc.com> Cc: llvm-dev at lists.llvm.org Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR On 21 May 2020, at 17:22, Chris Tetreault wrote: John, This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. While I’m at a loss to find a documented policy, I recall this thread (http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) where this claim was made and not disputed. The expected real benefits to this change are: 1) The names now match the semantics 2) It is now statically impossible to accidentally get the fixed number of elements from a scalable vector and 3) It forces everybody to fix their broken code. If we provided stability guarantees to downstream and out-of-tree codebases, then I might not agree that 3 is a benefit, but my understanding is that we do not provide this guarantee. … Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. This code is all broken already. I don’t think supporting common misuse of APIs in a codebase that does not provide stability guarantees is something we should be doing. The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed I agree. Unfortunately it happened, and our choices are to fix it or accept the technical debt forever. Perhaps this is part of the root of our disagreement. I consider scalable vector types to be an experimental/unstable feature, as many features are when they’re first added to the compiler. I have much lower standards for disrupting the early adopters of features like that; if scalable vectors need to be split out of VectorType, we should just do it. Analogously, when we upstream the pointer-authentication feature, we will be upstreaming a rather flawed representation that I definitely expect us to revise after the fact. That will be problematic for early adopters of LLVM’s pointer authentication support, but that’s totally acceptable. John. the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. The burden of creating the generalization should be placed on those who need it, I agree. However, once the generalization is in place, the burden is on everybody to use it correctly. The reason I’ve undertaken this refactor is because I found myself playing whack-a-mole with people adding new broken code after the fact. The previous API was very easy to misuse, so I don’t blame those people. Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? Everywhere that VectorType::getNumElements() is being called, we are either changing the code to cast to FixedVectorType, or we are updating the code to handle scalable vectors correctly. If the call site does not have test coverage with scalable vectors, this test coverage is being added. Even for obviously correct transformations such as `VectorType::get(SomeTy, SomeVecTy->getNumElements())` -> `VectorType::get(SomeTy, SomeVecTy->getElementCount())`, I have been required in code review to provide test coverage. We are taking this seriously. “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. Various languages implemented on top of LLVM have various different pointer types. However, the LLVM IR language only has one pointer type. The LLVM IR language has two types of vectors, and I think it’s reasonable to model them as a class hierarchy in this manner. I’m not familiar with the clang::PointerType situation, so I cannot pass judgement on it. Thanks, Christopher Tetreault From: John McCall <rjmccall at apple.com<mailto:rjmccall at apple.com>> Sent: Thursday, May 21, 2020 1:47 PM To: Chris Tetreault <ctetreau at quicinc.com<mailto:ctetreau at quicinc.com>> Cc: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org> Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR On 21 May 2020, at 16:01, Chris Tetreault wrote: Hi John, I’d like to address some points in your message. Practically speaking, this is going to break every out-of-tree frontend, backend, or optimization pass that supports SIMD types. My understanding is that the policy in LLVM development is that we do not let considerations for downstream and out-of-tree codebases affect the pace of development. This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. The C++ API is explicitly unstable. I maintain a downstream fork of LLVM myself, so I know the pain that this is causing because I get to fix all the issues in my internal codebase. However, the fix for downstream codebases is very simple: Just find all the places where it says VectorType, and change it to say FixedVectorType. … by having the VectorType type semantically repurposed out from under them. The documented semantics of VectorType prior to my RFC were that it is a generalization of all vector types. The VectorType contains an ElementCount, which is a pair of (bool, unsigned). If the bool is true, then the return value of getNumElements() is the minimum number of vector elements. If the bool is false, then it is the actual number of elements. My RFC has not changed these semantics. It will eventually delete a function that has been pervasively misused throughout the codebase, but the semantics remain the same. You are proposing a semantic change to VectorType to have it specifically be a fixed width vector. Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed; it should always have used a different type. Honestly, I’m not convinced your abstract base type is even going to be very useful in practice vs. just having a getVectorElementType() accessor that checks for both and otherwise returns null. … a particular largely-vendor-specific extension … All SIMD vectors are vendor specific extensions. Just because most of the most popular architectures have them does not make this not true. AArch64 and RISC-V have scalable vectors, so it is not just one architecture. It is the responsibility of all developers to ensure that they use the types correctly. It would be nice if the obvious thing to do is the correct thing to do. I’m not saying that we shouldn’t support scalable vector types. I’m saying that the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. … it’s much better for code that does support both to explicitly opt in by checking for and handling the more general type … This is how it will work. I am in the process of fixing up call sites that make fixed width assumptions so that they use FixedVectorType. Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? Because scalable vector types impose some major restrictions that aren’t imposed on normal vectors, and the static type system isn’t going to catch most of them. I think that it is important to ensure that things have clear sensible names, and to clean up historical baggage when the opportunity presents. “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. You have resigned yourself to doing a lot of work in pursuit of something that I really don’t think is actually an improvement. John. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200522/d68fc47d/attachment-0001.html>
Sander De Smalen via llvm-dev
2020-May-22 16:42 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
Hi John, Not sure if I've missed this, but is there a reason that Chris' suggestion to do a mechanical search/replace of VectorType -> FixedVectorType wouldn't work for your local changes? Given that your downstream changes interpret VectorType as a fixed vector type, it should be safe to do that. It will also be an effort that you'll only need to do once when you next merge with upstream master, after that you can just use FixedVectorType in your downstream repo. Chris has been doing some great work to split out fixed-width vectors from scalable vectors which is an important step towards preparing LLVM IR for scalable vectors. The bulk of mechanical changes have been done and a bunch of us are now working to ensure LLVM IR handles/distinguishes these vector types correctly. It would be a pity and great setback if that would be a wasted effort. We have a fortnightly SVE/SVE2 sync-up call with people in the LLVM community interested in scalable vectors where we normally discuss these things. If you want to join the call next Thursday [1], it seems like a fair topic to bring up in that meeting? Thanks, Sander [1] https://docs.google.com/document/d/1bkS8OKxAyawk6MVKrYkpYRqJtpw2iKGmHFUVWEDSyTQ> On 21 May 2020, at 23:32, John McCall via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > On 21 May 2020, at 17:22, Chris Tetreault wrote: > > John, > > This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. > > While I’m at a loss to find a documented policy, I recall this thread (http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) where this claim was made and not disputed. The expected real benefits to this change are: 1) The names now match the semantics 2) It is now statically impossible to accidentally get the fixed number of elements from a scalable vector and 3) It forces everybody to fix their broken code. If we provided stability guarantees to downstream and out-of-tree codebases, then I might not agree that 3 is a benefit, but my understanding is that we do not provide this guarantee. > > … Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. > > This code is all broken already. I don’t think supporting common misuse of APIs in a codebase that does not provide stability guarantees is something we should be doing. > > The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed > > I agree. Unfortunately it happened, and our choices are to fix it or accept the technical debt forever. > > Perhaps this is part of the root of our disagreement. I consider scalable vector types to be an experimental/unstable feature, as many features are when they’re first added to the compiler. I have much lower standards for disrupting the early adopters of features like that; if scalable vectors need to be split out of VectorType, we should just do it. > > Analogously, when we upstream the pointer-authentication feature, we will be upstreaming a rather flawed representation that I definitely expect us to revise after the fact. That will be problematic for early adopters of LLVM’s pointer authentication support, but that’s totally acceptable. > > John. > > the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. > > The burden of creating the generalization should be placed on those who need it, I agree. However, once the generalization is in place, the burden is on everybody to use it correctly. The reason I’ve undertaken this refactor is because I found myself playing whack-a-mole with people adding new broken code after the fact. The previous API was very easy to misuse, so I don’t blame those people. > > Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? > > Everywhere that VectorType::getNumElements() is being called, we are either changing the code to cast to FixedVectorType, or we are updating the code to handle scalable vectors correctly. If the call site does not have test coverage with scalable vectors, this test coverage is being added. Even for obviously correct transformations such as `VectorType::get(SomeTy, SomeVecTy->getNumElements())` -> `VectorType::get(SomeTy, SomeVecTy->getElementCount())`, I have been required in code review to provide test coverage. We are taking this seriously. > > “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. > > Various languages implemented on top of LLVM have various different pointer types. However, the LLVM IR language only has one pointer type. The LLVM IR language has two types of vectors, and I think it’s reasonable to model them as a class hierarchy in this manner. I’m not familiar with the clang::PointerType situation, so I cannot pass judgement on it. > > Thanks, > Christopher Tetreault > > From: John McCall <rjmccall at apple.com> > Sent: Thursday, May 21, 2020 1:47 PM > To: Chris Tetreault <ctetreau at quicinc.com> > Cc: llvm-dev at lists.llvm.org > Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR > > > On 21 May 2020, at 16:01, Chris Tetreault wrote: > > Hi John, > > I’d like to address some points in your message. > > Practically speaking, this is going to break every out-of-tree frontend, backend, or optimization pass that supports SIMD types. > > My understanding is that the policy in LLVM development is that we do not let considerations for downstream and out-of-tree codebases affect the pace of development. > > This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. > > The C++ API is explicitly unstable. I maintain a downstream fork of LLVM myself, so I know the pain that this is causing because I get to fix all the issues in my internal codebase. However, the fix for downstream codebases is very simple: Just find all the places where it says VectorType, and change it to say FixedVectorType. > > … by having the VectorType type semantically repurposed out from under them. > > The documented semantics of VectorType prior to my RFC were that it is a generalization of all vector types. The VectorType contains an ElementCount, which is a pair of (bool, unsigned). If the bool is true, then the return value of getNumElements() is the minimum number of vector elements. If the bool is false, then it is the actual number of elements. My RFC has not changed these semantics. It will eventually delete a function that has been pervasively misused throughout the codebase, but the semantics remain the same. You are proposing a semantic change to VectorType to have it specifically be a fixed width vector. > > Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed; it should always have used a different type. Honestly, I’m not convinced your abstract base type is even going to be very useful in practice vs. just having a getVectorElementType() accessor that checks for both and otherwise returns null. > > … a particular largely-vendor-specific extension … > > All SIMD vectors are vendor specific extensions. Just because most of the most popular architectures have them does not make this not true. AArch64 and RISC-V have scalable vectors, so it is not just one architecture. It is the responsibility of all developers to ensure that they use the types correctly. It would be nice if the obvious thing to do is the correct thing to do. > > I’m not saying that we shouldn’t support scalable vector types. I’m saying that the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. > > … it’s much better for code that does support both to explicitly opt in by checking for and handling the more general type … > > This is how it will work. I am in the process of fixing up call sites that make fixed width assumptions so that they use FixedVectorType. > > Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? Because scalable vector types impose some major restrictions that aren’t imposed on normal vectors, and the static type system isn’t going to catch most of them. > > I think that it is important to ensure that things have clear sensible names, and to clean up historical baggage when the opportunity presents. > > “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. > > You have resigned yourself to doing a lot of work in pursuit of something that I really don’t think is actually an improvement. > > John. > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Mehdi AMINI via llvm-dev
2020-May-22 20:01 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
On Thu, May 21, 2020 at 2:22 PM Chris Tetreault via llvm-dev < llvm-dev at lists.llvm.org> wrote:> John, > > > This is not categorically true, no. When we make changes that require > large-scale updates for downstream codebases, we do so because there’s a > real expected benefit to it. For the most part, we do make some effort to > keep existing source interfaces stable. > > While I’m at a loss to find a documented policy, I recall this thread ( > http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) where > this claim was made and not disputed. >John description is maybe slightly more conservative than how I've been seeing it: there is always a tension there and some balance to find, but we usually err on the side of doing what's best upstream, while avoiding "unnecessary churn". Even without over-emphasizing downstream, other folks upstream are working on patches and too much churn on the main APIs makes everyone else's on-going patches harder to carry over. In the case of this feature, the angle seems maybe more that this is introducing something experimental and we don't how much extra churn will occur until this stabilize. With this angle the priority is to reduce the disruption on the "stable" long-lived VectorType: it isn't immutable but you don't want to change it every other months for the new couple of years. Ultimately I'd rather still consider what makes the most sense upstream for the design (where do we want to be in two years) and try to get there. This does not require to preserve the APIs, but the chose path to get should likely favor doing "some" extra churn/detour in introducing the new concepts when it reduces significantly the churn to the "stable" existing classes/API. That may fit what John considered under "we do make some effort to keep existing source interfaces"? This is how I understand the approach for "pointer-authentication feature" that was mentioned as an example. Hopefully this makes sense? Thanks again for all the refactoring work to introduce SVE Chris! This is no small task :) Best, -- Mehdi> The expected real benefits to this change are: 1) The names now match the > semantics 2) It is now statically impossible to accidentally get the fixed > number of elements from a scalable vector and 3) It forces everybody to fix > their broken code. If we provided stability guarantees to downstream and > out-of-tree codebases, then I might not agree that 3 is a benefit, but my > understanding is that we do not provide this guarantee. > > > > > … Probably 99% of the code using VectorType semantically requires it to > be a fixed-width vector. > > > > This code is all broken already. I don’t think supporting common misuse of > APIs in a codebase that does not provide stability guarantees is something > we should be doing. > > > > > The generalization of VectorType to scalable vector types was a > representational shortcut that should never have been allowed > > > > I agree. Unfortunately it happened, and our choices are to fix it or > accept the technical debt forever. > > > > > the burden of generalization should usually fall on the people who need > to use the generalization, and otherwise we should aim to keep APIs stable > when there’s no harm to it. > > > > The burden of creating the generalization should be placed on those who > need it, I agree. However, once the generalization is in place, the burden > is on everybody to use it correctly. The reason I’ve undertaken this > refactor is because I found myself playing whack-a-mole with people adding > new broken code after the fact. The previous API was very easy to misuse, > so I don’t blame those people. > > > Are you actually auditing and testing them all to work for scalable > vector types, or are you just fixing the obvious compile failures? > > Everywhere that VectorType::getNumElements() is being called, we are > either changing the code to cast to FixedVectorType, or we are updating the > code to handle scalable vectors correctly. If the call site does not have > test coverage with scalable vectors, this test coverage is being added. > Even for obviously correct transformations such as `VectorType::get(SomeTy, > SomeVecTy->getNumElements())` -> `VectorType::get(SomeTy, > SomeVecTy->getElementCount())`, I have been required in code review to > provide test coverage. We are taking this seriously. > > > “Vector” has a traditional and dominant meaning as a fixed-width SIMD > type, and the fact that you’ve introduced a generalization doesn’t change > that. Clang supports multiple kinds of pointer, but we still reserve > clang::PointerType for C pointers instead of making it an abstract > superclass, thus letting our sense of logic introduce a million bugs > through accidental generalization throughout the compiler. > > Various languages implemented on top of LLVM have various different > pointer types. However, the LLVM IR language only has one pointer type. The > LLVM IR language has two types of vectors, and I think it’s reasonable to > model them as a class hierarchy in this manner. I’m not familiar with the > clang::PointerType situation, so I cannot pass judgement on it. > > > > Thanks, > > Christopher Tetreault > > > > *From:* John McCall <rjmccall at apple.com> > *Sent:* Thursday, May 21, 2020 1:47 PM > *To:* Chris Tetreault <ctetreau at quicinc.com> > *Cc:* llvm-dev at lists.llvm.org > *Subject:* [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of > VectorType in the IR > > > > On 21 May 2020, at 16:01, Chris Tetreault wrote: > > Hi John, > > I’d like to address some points in your message. > > Practically speaking, this is going to break every out-of-tree frontend, > backend, or optimization pass that supports SIMD types. > > My understanding is that the policy in LLVM development is that we do not > let considerations for downstream and out-of-tree codebases affect the pace > of development. > > This is not categorically true, no. When we make changes that require > large-scale updates for downstream codebases, we do so because there’s a > real expected benefit to it. For the most part, we do make some effort to > keep existing source interfaces stable. > > The C++ API is explicitly unstable. I maintain a downstream fork of LLVM > myself, so I know the pain that this is causing because I get to fix all > the issues in my internal codebase. However, the fix for downstream > codebases is very simple: Just find all the places where it says > VectorType, and change it to say FixedVectorType. > > … by having the VectorType type semantically repurposed out from under > them. > > The documented semantics of VectorType prior to my RFC were that it is a > generalization of all vector types. The VectorType contains an > ElementCount, which is a pair of (bool, unsigned). If the bool is true, > then the return value of getNumElements() is the minimum number of vector > elements. If the bool is false, then it is the actual number of elements. > My RFC has not changed these semantics. It will eventually delete a > function that has been pervasively misused throughout the codebase, but the > semantics remain the same. You are proposing a semantic change to > VectorType to have it specifically be a fixed width vector. > > Probably 99% of the code using VectorType semantically requires it to be a > fixed-width vector. The generalization of VectorType to scalable vector > types was a representational shortcut that should never have been allowed; > it should always have used a different type. Honestly, I’m not convinced > your abstract base type is even going to be very useful in practice vs. > just having a getVectorElementType() accessor that checks for both and > otherwise returns null. > > … a particular largely-vendor-specific extension … > > All SIMD vectors are vendor specific extensions. Just because most of the > most popular architectures have them does not make this not true. AArch64 > and RISC-V have scalable vectors, so it is not just one architecture. It is > the responsibility of all developers to ensure that they use the types > correctly. It would be nice if the obvious thing to do is the correct thing > to do. > > I’m not saying that we shouldn’t support scalable vector types. I’m saying > that the burden of generalization should usually fall on the people who > need to use the generalization, and otherwise we should aim to keep APIs > stable when there’s no harm to it. > > … it’s much better for code that does support both to explicitly opt in by > checking for and handling the more general type … > > This is how it will work. I am in the process of fixing up call sites that > make fixed width assumptions so that they use FixedVectorType. > > Are you actually auditing and testing them all to work for scalable vector > types, or are you just fixing the obvious compile failures? Because > scalable vector types impose some major restrictions that aren’t imposed on > normal vectors, and the static type system isn’t going to catch most of > them. > > I think that it is important to ensure that things have clear sensible > names, and to clean up historical baggage when the opportunity presents. > > “Vector” has a traditional and dominant meaning as a fixed-width SIMD > type, and the fact that you’ve introduced a generalization doesn’t change > that. Clang supports multiple kinds of pointer, but we still reserve > clang::PointerType for C pointers instead of making it an abstract > superclass, thus letting our sense of logic introduce a million bugs > through accidental generalization throughout the compiler. > > You have resigned yourself to doing a lot of work in pursuit of something > that I really don’t think is actually an improvement. > > John. > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200522/13059e13/attachment.html>
Chris Tetreault via llvm-dev
2020-May-23 00:22 UTC
[llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR
Mehdi, I keep hearing that scalable vectors are experimental, and I don’t think that this is the case. The initial introduction of the type as a flag on VectorType was the experimental first step. Now we are taking the step where we consider how the initial step played out, and adapt with a well thought out solution. This patch makes sure that the meaning of the long lived “stable” fixed width vector type is not impacted by scalable vectors, or some other future vector type. If we do this change now, it will be done and we won’t have this problem in the future. The goal of this patch is to minimize future churn. If “99% of external code only cares about fixed width vectors”, then this code can be secure that it’s use of the type called FixedVectorType will not be impacted by other types of vectors because the work was done to separate it out into its own thing. Thanks, Christopher Tetreault From: Mehdi AMINI <joker.eph at gmail.com> Sent: Friday, May 22, 2020 1:02 PM To: Chris Tetreault <ctetreau at quicinc.com> Cc: John McCall <rjmccall at apple.com>; llvm-dev at lists.llvm.org Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR On Thu, May 21, 2020 at 2:22 PM Chris Tetreault via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>> wrote: John,> This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable.While I’m at a loss to find a documented policy, I recall this thread (http://lists.llvm.org/pipermail/llvm-dev/2020-February/139207.html) where this claim was made and not disputed. John description is maybe slightly more conservative than how I've been seeing it: there is always a tension there and some balance to find, but we usually err on the side of doing what's best upstream, while avoiding "unnecessary churn". Even without over-emphasizing downstream, other folks upstream are working on patches and too much churn on the main APIs makes everyone else's on-going patches harder to carry over. In the case of this feature, the angle seems maybe more that this is introducing something experimental and we don't how much extra churn will occur until this stabilize. With this angle the priority is to reduce the disruption on the "stable" long-lived VectorType: it isn't immutable but you don't want to change it every other months for the new couple of years. Ultimately I'd rather still consider what makes the most sense upstream for the design (where do we want to be in two years) and try to get there. This does not require to preserve the APIs, but the chose path to get should likely favor doing "some" extra churn/detour in introducing the new concepts when it reduces significantly the churn to the "stable" existing classes/API. That may fit what John considered under "we do make some effort to keep existing source interfaces"? This is how I understand the approach for "pointer-authentication feature" that was mentioned as an example. Hopefully this makes sense? Thanks again for all the refactoring work to introduce SVE Chris! This is no small task :) Best, -- Mehdi The expected real benefits to this change are: 1) The names now match the semantics 2) It is now statically impossible to accidentally get the fixed number of elements from a scalable vector and 3) It forces everybody to fix their broken code. If we provided stability guarantees to downstream and out-of-tree codebases, then I might not agree that 3 is a benefit, but my understanding is that we do not provide this guarantee.> … Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector.This code is all broken already. I don’t think supporting common misuse of APIs in a codebase that does not provide stability guarantees is something we should be doing.> The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowedI agree. Unfortunately it happened, and our choices are to fix it or accept the technical debt forever.> the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it.The burden of creating the generalization should be placed on those who need it, I agree. However, once the generalization is in place, the burden is on everybody to use it correctly. The reason I’ve undertaken this refactor is because I found myself playing whack-a-mole with people adding new broken code after the fact. The previous API was very easy to misuse, so I don’t blame those people.> Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures?Everywhere that VectorType::getNumElements() is being called, we are either changing the code to cast to FixedVectorType, or we are updating the code to handle scalable vectors correctly. If the call site does not have test coverage with scalable vectors, this test coverage is being added. Even for obviously correct transformations such as `VectorType::get(SomeTy, SomeVecTy->getNumElements())` -> `VectorType::get(SomeTy, SomeVecTy->getElementCount())`, I have been required in code review to provide test coverage. We are taking this seriously.> “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler.Various languages implemented on top of LLVM have various different pointer types. However, the LLVM IR language only has one pointer type. The LLVM IR language has two types of vectors, and I think it’s reasonable to model them as a class hierarchy in this manner. I’m not familiar with the clang::PointerType situation, so I cannot pass judgement on it. Thanks, Christopher Tetreault From: John McCall <rjmccall at apple.com<mailto:rjmccall at apple.com>> Sent: Thursday, May 21, 2020 1:47 PM To: Chris Tetreault <ctetreau at quicinc.com<mailto:ctetreau at quicinc.com>> Cc: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org> Subject: [EXT] Re: [llvm-dev] [RFC] Refactor class hierarchy of VectorType in the IR On 21 May 2020, at 16:01, Chris Tetreault wrote: Hi John, I’d like to address some points in your message. Practically speaking, this is going to break every out-of-tree frontend, backend, or optimization pass that supports SIMD types. My understanding is that the policy in LLVM development is that we do not let considerations for downstream and out-of-tree codebases affect the pace of development. This is not categorically true, no. When we make changes that require large-scale updates for downstream codebases, we do so because there’s a real expected benefit to it. For the most part, we do make some effort to keep existing source interfaces stable. The C++ API is explicitly unstable. I maintain a downstream fork of LLVM myself, so I know the pain that this is causing because I get to fix all the issues in my internal codebase. However, the fix for downstream codebases is very simple: Just find all the places where it says VectorType, and change it to say FixedVectorType. … by having the VectorType type semantically repurposed out from under them. The documented semantics of VectorType prior to my RFC were that it is a generalization of all vector types. The VectorType contains an ElementCount, which is a pair of (bool, unsigned). If the bool is true, then the return value of getNumElements() is the minimum number of vector elements. If the bool is false, then it is the actual number of elements. My RFC has not changed these semantics. It will eventually delete a function that has been pervasively misused throughout the codebase, but the semantics remain the same. You are proposing a semantic change to VectorType to have it specifically be a fixed width vector. Probably 99% of the code using VectorType semantically requires it to be a fixed-width vector. The generalization of VectorType to scalable vector types was a representational shortcut that should never have been allowed; it should always have used a different type. Honestly, I’m not convinced your abstract base type is even going to be very useful in practice vs. just having a getVectorElementType() accessor that checks for both and otherwise returns null. … a particular largely-vendor-specific extension … All SIMD vectors are vendor specific extensions. Just because most of the most popular architectures have them does not make this not true. AArch64 and RISC-V have scalable vectors, so it is not just one architecture. It is the responsibility of all developers to ensure that they use the types correctly. It would be nice if the obvious thing to do is the correct thing to do. I’m not saying that we shouldn’t support scalable vector types. I’m saying that the burden of generalization should usually fall on the people who need to use the generalization, and otherwise we should aim to keep APIs stable when there’s no harm to it. … it’s much better for code that does support both to explicitly opt in by checking for and handling the more general type … This is how it will work. I am in the process of fixing up call sites that make fixed width assumptions so that they use FixedVectorType. Are you actually auditing and testing them all to work for scalable vector types, or are you just fixing the obvious compile failures? Because scalable vector types impose some major restrictions that aren’t imposed on normal vectors, and the static type system isn’t going to catch most of them. I think that it is important to ensure that things have clear sensible names, and to clean up historical baggage when the opportunity presents. “Vector” has a traditional and dominant meaning as a fixed-width SIMD type, and the fact that you’ve introduced a generalization doesn’t change that. Clang supports multiple kinds of pointer, but we still reserve clang::PointerType for C pointers instead of making it an abstract superclass, thus letting our sense of logic introduce a million bugs through accidental generalization throughout the compiler. You have resigned yourself to doing a lot of work in pursuit of something that I really don’t think is actually an improvement. John. _______________________________________________ LLVM Developers mailing list llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200523/edad9f59/attachment.html>