[flang-commits] [flang] ddb68f3 - [flang] Initial support for FastMathAttr setup in FirOpBuilder.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Mon Nov 7 09:03:55 PST 2022


Author: Slava Zakharin
Date: 2022-11-07T09:03:46-08:00
New Revision: ddb68f36ae3a7ecb833e3ddf2ab8afe6ed509651

URL: https://github.com/llvm/llvm-project/commit/ddb68f36ae3a7ecb833e3ddf2ab8afe6ed509651
DIFF: https://github.com/llvm/llvm-project/commit/ddb68f36ae3a7ecb833e3ddf2ab8afe6ed509651.diff

LOG: [flang] Initial support for FastMathAttr setup in FirOpBuilder.

Provide FirOpBuilder::setFastMathFlags() to configure FastMathFlags
for the builder. Set FastMathAttr for operations based on FirOpBuilder
configuration via mlir::OpBuilder::Listener.

This is a little bit hacky solution, because we lose the ability
to hook other listeners to FirOpBuilder. There are also potential
issues with OpBuilder::clone() - the hook will be invoked for cloned
operations and will effectively overwrite FastMathAttr with the ones
configured in FirOpBuilder, which should not be happening.
We should teach mlir::OpBuilder about FastMathAttr setup in future.

Reviewed By: jeanPerier, kiranchandramohan

Differential Revision: https://reviews.llvm.org/D137390

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Builder/FIRBuilder.h
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 49fc22e830b4e..5a43b1705c749 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -35,13 +35,22 @@ class BoxValue;
 
 /// Extends the MLIR OpBuilder to provide methods for building common FIR
 /// patterns.
-class FirOpBuilder : public mlir::OpBuilder {
+class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
 public:
   explicit FirOpBuilder(mlir::Operation *op, const fir::KindMapping &kindMap)
-      : OpBuilder{op}, kindMap{kindMap} {}
+      : OpBuilder{op, /*listener=*/this}, kindMap{kindMap} {}
   explicit FirOpBuilder(mlir::OpBuilder &builder,
                         const fir::KindMapping &kindMap)
-      : OpBuilder{builder}, kindMap{kindMap} {}
+      : OpBuilder{builder}, kindMap{kindMap} {
+    setListener(this);
+  }
+
+  // The listener self-reference has to be updated in case of copy-construction.
+  FirOpBuilder(const FirOpBuilder &other)
+      : OpBuilder{other}, kindMap{other.kindMap}, fastMathFlags{
+                                                      other.fastMathFlags} {
+    setListener(this);
+  }
 
   /// Get the current Region of the insertion point.
   mlir::Region &getRegion() { return *getBlock()->getParent(); }
@@ -393,11 +402,31 @@ class FirOpBuilder : public mlir::OpBuilder {
                                    mlir::Value ub, mlir::Value step,
                                    mlir::Type type);
 
+  /// Set default FastMathFlags value for all operations
+  /// supporting mlir::arith::FastMathAttr that will be created
+  /// by this builder.
+  void setFastMathFlags(mlir::arith::FastMathFlags flags) {
+    fastMathFlags = flags;
+  }
+
   /// Dump the current function. (debug)
   LLVM_DUMP_METHOD void dumpFunc();
 
 private:
+  /// Set attributes (e.g. FastMathAttr) to \p op operation
+  /// based on the current attributes setting.
+  void setCommonAttributes(mlir::Operation *op) const;
+
+  /// FirOpBuilder hook for creating new operation.
+  void notifyOperationInserted(mlir::Operation *op) override {
+    setCommonAttributes(op);
+  }
+
   const KindMapping &kindMap;
+
+  /// FastMathFlags that need to be set for operations that support
+  /// mlir::arith::FastMathAttr.
+  mlir::arith::FastMathFlags fastMathFlags{};
 };
 
 } // namespace fir

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 984c2459cac66..59cc0583c24c5 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -571,6 +571,18 @@ mlir::Value fir::FirOpBuilder::genExtentFromTriplet(mlir::Location loc,
   return create<mlir::arith::SelectOp>(loc, cmp, div, zero);
 }
 
+void fir::FirOpBuilder::setCommonAttributes(mlir::Operation *op) const {
+  auto fmi = mlir::dyn_cast<mlir::arith::ArithFastMathInterface>(*op);
+  if (!fmi)
+    return;
+  // TODO: use fmi.setFastMathFlagsAttr() after D137114 is merged.
+  //       For now set the attribute by the name.
+  llvm::StringRef arithFMFAttrName = fmi.getFastMathAttrName();
+  if (fastMathFlags != mlir::arith::FastMathFlags::none)
+    op->setAttr(arithFMFAttrName, mlir::arith::FastMathFlagsAttr::get(
+                                      op->getContext(), fastMathFlags));
+}
+
 //===--------------------------------------------------------------------===//
 // ExtendedValue inquiry helper implementation
 //===--------------------------------------------------------------------===//

diff  --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index 83d3defd3d067..9defe496b9c05 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -528,3 +528,58 @@ TEST_F(FIRBuilderTest, getBaseTypeOf) {
     EXPECT_TRUE(fir::isDerivedWithLenParameters(array));
   }
 }
+
+TEST_F(FIRBuilderTest, genArithFastMath) {
+  auto builder = getBuilder();
+  auto ctx = builder.getContext();
+  auto loc = builder.getUnknownLoc();
+
+  auto realTy = mlir::FloatType::getF32(ctx);
+  auto arg = builder.create<fir::UndefOp>(loc, realTy);
+
+  // Test that FastMathFlags is 'none' by default.
+  mlir::Operation *op1 = builder.create<mlir::arith::AddFOp>(loc, arg, arg);
+  auto op1_fmi =
+      mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op1);
+  EXPECT_TRUE(op1_fmi);
+  auto op1_fmf = op1_fmi.getFastMathFlagsAttr().getValue();
+  EXPECT_EQ(op1_fmf, arith::FastMathFlags::none);
+
+  // Test that the builder is copied properly.
+  fir::FirOpBuilder builder_copy(builder);
+
+  arith::FastMathFlags FMF1 =
+      arith::FastMathFlags::contract | arith::FastMathFlags::reassoc;
+  builder.setFastMathFlags(FMF1);
+  arith::FastMathFlags FMF2 =
+      arith::FastMathFlags::nnan | arith::FastMathFlags::ninf;
+  builder_copy.setFastMathFlags(FMF2);
+
+  // Modifying FastMathFlags for the copy must not affect the original builder.
+  mlir::Operation *op2 = builder.create<mlir::arith::AddFOp>(loc, arg, arg);
+  auto op2_fmi =
+      mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op2);
+  EXPECT_TRUE(op2_fmi);
+  auto op2_fmf = op2_fmi.getFastMathFlagsAttr().getValue();
+  EXPECT_EQ(op2_fmf, FMF1);
+
+  // Modifying FastMathFlags for the original builder must not affect the copy.
+  mlir::Operation *op3 =
+      builder_copy.create<mlir::arith::AddFOp>(loc, arg, arg);
+  auto op3_fmi =
+      mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op3);
+  EXPECT_TRUE(op3_fmi);
+  auto op3_fmf = op3_fmi.getFastMathFlagsAttr().getValue();
+  EXPECT_EQ(op3_fmf, FMF2);
+
+  // Test that the builder copy inherits FastMathFlags from the original.
+  fir::FirOpBuilder builder_copy2(builder);
+
+  mlir::Operation *op4 =
+      builder_copy2.create<mlir::arith::AddFOp>(loc, arg, arg);
+  auto op4_fmi =
+      mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op4);
+  EXPECT_TRUE(op4_fmi);
+  auto op4_fmf = op4_fmi.getFastMathFlagsAttr().getValue();
+  EXPECT_EQ(op4_fmf, FMF1);
+}


        


More information about the flang-commits mailing list