# Fastmath flags support in LLVM dialect ops

**URL:** <https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341>\
**Category:** MLIR\
**Created:** [December 3, 2020, 12:23pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341 "2020-12-03T12:23:46Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 3, 2020, 12:23pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/1 "2020-12-03T12:23:47Z")

</div>

Hi, I need fastmath flags support in LLVM dialect ops [https://llvm.org/docs/LangRef.html#fast-math-flags](https://llvm.org/docs/LangRef.html#fast-math-flags)

Here is my initial attempt [https://reviews.llvm.org/D92485](https://reviews.llvm.org/D92485) where they are implemented just as array-of-strings attribute, but this approach has its issues.

Any ideas how they should like C++ api wise and in IR?

---

<div class="post-metadata">

**Author:** ![ftynse](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/ftynse/32/18644_2.png) [@ftynse](https://discourse.llvm.org/u/ftynse)\
**Post date:** [December 3, 2020, 4:17pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/2 "2020-12-03T16:17:01Z")

</div>

As I suggested on the review thread, independent UnitAttributes looks suitable. So does a custom attribute type backed by a bitfield. There are tradeoffs between these two.

C++ API should not be different from any other attribute.

An op interface would not be necessary unless one intends to process ops with FMF in an opaque way, e.g. without knowing what is the actual op.

It’s unclear to me how do you intend to _target_ these ops in the LLVM dialect. If we need an equivalent in standard, this deserves a much more elaborate proposal.

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 3, 2020, 4:48pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/3 "2020-12-03T16:48:41Z")

</div>

> It’s unclear to me how do you intend to _target_ these ops in the LLVM dialect. If we need an equivalent in standard, this deserves a much more elaborate proposal.

For now I am going to add pass to our pipeline which runs after std-\>llvm conversion and sets these flags on all llvm ops based on some global option

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 4, 2020, 12:05pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/4 "2020-12-04T12:05:39Z")

</div>

> As I suggested on the review thread, independent UnitAttributes looks suitable

To do this we need to add `UnitAttr:$nnan, UnitAttr:$ninf, UnitAttr:$fast, ...etc` to each op argument list (at least to `LLVM_FCmpOp`, `LLVM_FloatArithmeticOp` and `LLVM_CallOp`), is there any way to do this without copypaste? This will also generate build functions with 8 consecutive bool params.

---

<div class="post-metadata">

**Author:** ![ftynse](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/ftynse/32/18644_2.png) [@ftynse](https://discourse.llvm.org/u/ftynse)\
**Post date:** [December 4, 2020, 12:54pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/5 "2020-12-04T12:54:36Z")

</div>

> [@Hardcode84](#):
>
> To do this we need to add `UnitAttr:$nnan, UnitAttr:$ninf, UnitAttr:$fast, ...etc` to each op argument list (at least to `LLVM_FCmpOp` , `LLVM_FloatArithmeticOp` and `LLVM_CallOp` ),

Yes, one can always do something like

```auto
def FastMathFlags {
  dag args = (ins UnitAttr:$nnan, UnitAttr:$ninf, ...);
}
def ...Op {
  dag properArgs = (ins LLVM_Type:$lhs, LLVM_Type:$rhs, ...);
  let arguments = !con(properArgs, args);
}

```

this can be further wrapper in classes to avoid concatenation in every op. `OpBase.td` and `LLVM_OpBase.td` are good source of inspiration of clever tablegen uses.

> [@Hardcode84](#):
>
> This will also generate build functions with 8 consecutive bool params.

We can always improve ODS backend to properly handle trailing default values. This will, however, add a verifier that only the known attributes are used.

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 4, 2020, 1:18pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/6 "2020-12-04T13:18:29Z")

</div>

Also, how our `build` function for this should like? Function with 8 bool params is not very user friendly.

---

<div class="post-metadata">

**Author:** ![ftynse](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/ftynse/32/18644_2.png) [@ftynse](https://discourse.llvm.org/u/ftynse)\
**Post date:** [December 4, 2020, 1:30pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/7 "2020-12-04T13:30:51Z")

</div>

I am open to propositions 🙂

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 4, 2020, 2:03pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/8 "2020-12-04T14:03:51Z")

</div>

We can have separate bitfield enum just to pass into `build` function, but it can be confusing to users to have separate enum just for this.

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/clattner/32/187_2.png) [@clattner](https://discourse.llvm.org/u/clattner)\
**Post date:** [December 4, 2020, 4:59pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/9 "2020-12-04T16:59:15Z")

</div>

I’d recommend pulling (or reimplementing) [swift::OptionSet](https://github.com/apple/swift/blob/main/include/swift/Basic/OptionSet.h) up to LLVM’s ADT library, and using that. It is exactly what we’re looking for here, a typed/named collection of specific boolean options. We could then have ODS turn a “pile of unit attributes” into an OptionSet implicitly.

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/clattner/32/187_2.png) [@clattner](https://discourse.llvm.org/u/clattner)\
**Post date:** [December 4, 2020, 5:01pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/10 "2020-12-04T17:01:34Z")

</div>

Just to make it clear, you use it in conjunction with an enum. There are a [bunch of examples in this file](https://github.com/apple/swift/blob/main/include/swift/AST/Decl.h#L3244), e.g.:

```auto
  enum SemanticInfoFlags : uint8_t {
    // Is the raw type valid?
    HasComputedRawType = 1 << 0,
    // Is the complete set of (auto-incremented) raw values available?
    HasFixedRawValues = 1 << 1,
    // Is the complete set of raw values type checked?
    HasFixedRawValuesAndTypes = 1 << 2,
  };
  OptionSet<SemanticInfoFlags> SemanticFlags;

```

---

<div class="post-metadata">

**Author:** ![ftynse](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/ftynse/32/18644_2.png) [@ftynse](https://discourse.llvm.org/u/ftynse)\
**Post date:** [December 4, 2020, 5:20pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/11 "2020-12-04T17:20:16Z")

</div>

> [@clattner](#):
>
> I’d recommend pulling (or reimplementing) [swift::OptionSet](https://github.com/apple/swift/blob/main/include/swift/Basic/OptionSet.h) up to LLVM’s ADT library, and using that. It is exactly what we’re looking for here, a typed/named collection of specific boolean options. We could then have ODS turn a “pile of unit attributes” into an OptionSet implicitly.

That would be a nice addition! “Bag of unit attributes” sounds like common pattern.

---

<div class="post-metadata">

**Author:** ![mehdi\_amini](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/mehdi_amini/32/25595_2.png) [@mehdi\_amini](https://discourse.llvm.org/u/mehdi_amini)\
**Post date:** [December 4, 2020, 11:37pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/12 "2020-12-04T23:37:18Z")

</div>

Is it similar to LLVM [BitmaskEnum](https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/ADT/BitmaskEnum.h)?

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/clattner/32/187_2.png) [@clattner](https://discourse.llvm.org/u/clattner)\
**Post date:** [December 5, 2020, 5:17am UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/13 "2020-12-05T05:17:23Z")

</div>

Looks similar, appears to lose the distinction between a set and a single enum, but it is hard to tell.

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 9, 2020, 7:21pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/14 "2020-12-09T19:21:01Z")

</div>

So, what’s the decision?

---

<div class="post-metadata">

**Author:** ![mehdi\_amini](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/mehdi_amini/32/25595_2.png) [@mehdi\_amini](https://discourse.llvm.org/u/mehdi_amini)\
**Post date:** [December 9, 2020, 8:38pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/15 "2020-12-09T20:38:08Z")

</div>

I’m fine either way: `UnitAttr` or BitmaskEnum. I suspect the latter will be more friendly for the build method and other APIs, but will require more effort on the printing/parsing helper needed (maybe a new TableGen type?).

---

<div class="post-metadata">

**Author:** ![Hardcode84](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/hardcode84/32/793_2.png) [@Hardcode84](https://discourse.llvm.org/u/Hardcode84)\
**Post date:** [December 15, 2020, 6:11pm UTC](https://discourse.llvm.org/t/fastmath-flags-support-in-llvm-dialect-ops/2341/16 "2020-12-15T18:11:31Z")

</div>

Updated review. I went with custom attribute approach as there were no good decision how to handle `build` with bunch unit attrs.

Some more comments:

- Have to change bunch of unrelated tests to handle possible new ops attributes, I would like to avoid that but have no ideas how to do this
- Used `IntegerAttributeStorage` for my bitfield attribute but had to do some ugly relative includes for `AttributeDetail.h` as it not part of public headers, any ideas how to do this properly
- It would be nice to have a way to get list of all enum values (tblgen generated)
- `DefaultValuedAttr` require `constBuilderCall` to be present but not enforces that and tblgen just silently generate invalid C++ code in that case
