[PATCH] D113107: Support of expression granularity for _Float16.

Phoebe Wang via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 21 20:02:19 PDT 2022

pengfei added inline comments.

Comment at: clang/lib/CodeGen/CGExprComplex.cpp:896
+ComplexPairTy ComplexExprEmitter::EmitPromoted(const Expr *E) {
+  if (auto *BinOp = dyn_cast<BinaryOperator>(E->IgnoreParens())) {
rjmccall wrote:
> pengfei wrote:
> > rjmccall wrote:
> > > zahiraam wrote:
> > > > rjmccall wrote:
> > > > > `EmitPromoted` should take the promotion type.
> > > > > 
> > > > > You are missing the logic in this file which handles *unpromoted* emission (where you have a binary operator but the context wants an unpromoted value) by recognizing that you need to do a promoted operation and then truncate.
> > > > Sorry but not sure what you mean here. A case where we don't want any promotion would be:
> > > > 
> > > > float _Complex add(float _Complex a, float _Complex b) {
> > > >   return a + b;
> > > > }
> > > > 
> > > > In this case, getPromotionType would return the null type and EmitBinOps would just go through the  "older" control path where there is no promotion.
> > > > Unless I misunderstood your comment?
> > > > 
> > > > 
> > > I'm talking about the unpromoted emission path for an operation that we want to *internally* promote.  So like your example but using `_Float16` — we want to emit the binary `+` as a `float` operation, but the context needs an unpromoted value because it's going to be returned.
> > > 
> > > The promoted emission path (the various `EmitPromoted` methods) represents a request by the caller to produce a result that doesn't match the formal type of the expression.  The normal emission path `Visit` etc.) represents a request by the caller to produce a result normally, i.e. one that matches the formal type.  In general, we always start in the latter because arbitrary contexts always expect a value of the formal type; it's only these recursive calls within promoted emitters that contextually want a promoted value.
> > > 
> > > In your current patch, you're entering the promoted path by special-casing one context that frequently terminates promoted emission: `EmitComplexExprIntoLValue`, which is used for things like assignment.  That's not the right way to handle it, though.  Instead, you should do like I asked you to do with the scalar emitter, which is to recognize in the normal emission path for a promotable operation (like binary `+`) that you need to promote the operation and then unpromote the result.  Then things like `EmitComplexExprIntoLValue` will continue to simply enter the normal path because that's the kind of value they need, and the promotion logic will do the right thing from there to ensure we don't emit a `_Float16` operation in LLVM IR.
> > > 
> > > Incidentally, I thought of another context that you ought to do promotion for: when we're converting a promotable value to a larger floating-point type, we should presumably convert the promoted value directly rather than truncating it to the unpromoted type before the conversion.
> > I'm not familiar with the FE details, but I understand the background is just to promote expressions that have more than one operation. So I agree with @zahiraam, and
> > > to ensure we don't emit a _Float16 operation in LLVM IR
> > is not what we expected here.
> > 
> > `_Float16` is a ABI type for which a target supported has to lower any `_Float16` operations in LLVM IR. See what we have done on X86 backend by D107082.
> > 
> > That said, a single `a + b` can be and should be emitted as `%c = fadd half %a, %b`.
> Well, you can provide operation-by-operation lowering support if you want to, but what's going to come out of Clang IRGen in this mode is not going to rely on it.  It's far easier to just emit these operations differently, always using `float`, than to try to recognize the special cases where all the inputs are naturally `half` and so you might as well emit a `half` operation.
> And I think the postcondition that `half` operations don't come out of IRGen is a generally useful property even if you've already written this lowering code.  Among other things, it makes it easy to test that you haven't missed a case where you should be doing promoted emission.
We define `_Float16` as ABI type and require targets to support the ABI lowering. See https://clang.llvm.org/docs/LanguageExtensions.html#half-precision-floating-point Promoting in FE doesn't mean it works on any targets by default, so I think it's not much useful.
We need to support `-fexcess-precision=16` the same as GCC does, it's easier to do nothing than promote and then truncate each of the operations in FE.
I think in general, lowering operations for a type is a business of backend. We still need backend to do so for other FEs even we do it in Clang. A recent example is BF16, which people chose to lower in backend rather than mlir, see D126444.

> Among other things, it makes it easy to test that you haven't missed a case where you should be doing promoted emission.
I don't understand, how can we check the missed cases if the promotion was done in FE?



More information about the cfe-commits mailing list