[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

Bevin Hansson via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 20 05:09:31 PDT 2018


ebevhan added a comment.

In https://reviews.llvm.org/D50616#1204588, @leonardchan wrote:

> Would it be simpler instead just to have the logic contained in the virtual function for `TargetCodeGenInfo` as opposed to returning `nullptr` since any custom target will end up overriding it anyway and ideally not return `nullptr`?


I guess that's also possible. I figured it would be clearer to have the generic logic in the more obvious location (CGExprScalar) and fall back to the custom handling if needed. Many of the handlers in TargetCodeGenInfo are empty.

> I haven't brought this up to llvm-dev, but the main reason for why we decided to only implement this in clang was because we thought it would be a lot harder pushing a new type into upstream llvm, especially since a lot of the features can be supported on the frontend using clang's existing infrastructure. We are open to adding fixed point types to LLVM IR in the future though once all the frontend stuff is laid out and if the community is willing to accept it.

I know there are multiple threads on llvm-dev asking about fixed-point support (some of them from us) and the verdict usually seems to be "no new types, use integers and intrinsics". This has worked fairly well for us, so it should be possible to adapt the design for upstream if there is a desire to have it.

I do not think a new type is required. As there are no in-tree architectures with native fixed-point support (as far as I know? Does AVR or ARM support it, perhaps? Probably not enough to cover the entire E-C spec, though.), there isn't really much to warrant adding a new type (or even new IR operators) for it. Furthermore, many of the operations on fixed-point are simple integer operations (except ones like saturation/saturating operations, multiplication, division etc) so those would be better off implemented in terms of those operators rather than inventing new ones that do pretty much the same thing.

In https://reviews.llvm.org/D50616#1204754, @rjmccall wrote:

> Very few things in LLVM actually try to exhaustively handle all operations.  There are a
>  couple of generic predicates on `Instruction` like `mayHaveSideEffects`, there's
>  serialization/`.ll`-writing, and there's code-gen.  The first two are not hard at all
>  to implement, and it'd be quite simple to write a legalization pass in code-gen that
>  turns all these operations into integer operations and which could easily be customized
>  to support targets that want to do something more precise.


I certainly support the idea of representing some (not all) fixed-point operations as intrinsics (or instructions, although I suspect that's more work than one might think) and converting them into integer instructions for targets which do not care to support the specific operation natively. A type is overkill; fixed-point values **are** 'bags of bits' like LLVM integers, just with a different interpretation of the bits. It's no different than the distinction between signed and unsigned, and we model that on the LLVM level through the operations rather than through the types.

Creating instruction/intrinsic definitions of fixed-point operations does come with problems. If an IR producer wants to emit fixed-point operations with slightly different semantics than what our instructions/intrinsics have, they're out of luck. It might also be a problem for targets that have fixed-point support, but cannot perform the operations in exactly the same manner as the IR operation specifies. Making the semantics of the operation too tight could cause this to happen, but making them too loose makes it hard to really do anything with it. This is another argument for frontend customization. Every operation also introduces a bit of optimization/codegen work, unlike pure integer operations which the passes already know.

Still, I think intrinsics for the complicated operations would provide a good balance.

> The advantages of having real IR support include:
> 
> - It's significant simpler for frontends.  All of this logic in Clang will need to be reimplemented in any other frontend that wants to support fixed-point types.

As I mentioned, this only simplifies things if the semantics of the operations work for the other frontend/language/target.

> 
> 
> - It's much easier to test.  The frontend needs to handle a lot of different code patterns that ultimately turn into the same small set of basic operations, like compound arithmetic and atomic operations and a million different things that are supposed to trigger implicit conversions.  It's ver frustrating to write tests for these things when constants aren't readable and the generated IR for every operation is a ten-instruction sequence.

I think this is primarily a problem for saturating operations, as those require a whole bunch of conditional assignment. Nonsaturating multiplication is only about 5 instructions, but it's still useful to have an operation for it, and division is about the same (although I have some input on division that might make it a bit more complex than that).

> 
> 
> - It's much easier to analyze and optimize.  I'm sure some fixed-point optimizations can be done generically over the underlying integer ops, but many others would be much more difficult if not impossible — e.g. I would assume that the lowering of padded unsigned values exploits an assumption that the padding bit is zero, which a generic optimization cannot know.

I think the representation that we landed on (for now) was that the padding bit is undefined rather than zero. I'm not sure I'm a fan of that representation, though.

If it was the case that it always was zero and we only use integer operations, this property should shine through, though. It would be a deficiency in the integer analysis otherwise.

> 
> 
> - All those ten-instruction sequences add up in their compile-time impact on every stage of the pipeline.
> 
>   I'm not saying it's an open-and-shut case, but LLVM is supposed to be an abstraction layer over more than just the concerns of code-generation, and even those concerns don't obviously point towards frontend expansion.
> 
>   Like I said, if this is just a hobby and we don't really care about supporting this as a feature beyond just checking a box, frontend expansion is definitely the easier approach for checking that box.  But if we want a high-quality implementation of fixed-point types, we should represent them directly in LLVM IR.

The former is definitely what has happened to the C99 _Complex feature, and it would be nice if we could avoid that for fixed-point.

Should we discuss this with someone on the LLVM side?


Repository:
  rC Clang

https://reviews.llvm.org/D50616





More information about the cfe-commits mailing list