[flang-commits] [flang] b3d1f07 - [flang] Lower real constant

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Tue Feb 22 23:28:08 PST 2022


Author: Valentin Clement
Date: 2022-02-23T08:27:54+01:00
New Revision: b3d1f073de971f7597ba937d8065dbba56cd8fc7

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

LOG: [flang] Lower real constant

This patch handles lowering of real constant.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: PeteSteinfeld

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

Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Co-authored-by: Jean Perier <jperier at nvidia.com>

Added: 
    

Modified: 
    flang/lib/Lower/ConvertExpr.cpp
    flang/lib/Lower/ConvertType.cpp
    flang/test/Lower/assignment.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 76bee213c96b6..013adb797da93 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -15,6 +15,7 @@
 #include "flang/Evaluate/real.h"
 #include "flang/Evaluate/traverse.h"
 #include "flang/Lower/AbstractConverter.h"
+#include "flang/Lower/ConvertType.h"
 #include "flang/Lower/IntrinsicCall.h"
 #include "flang/Lower/SymbolMap.h"
 #include "flang/Lower/Todo.h"
@@ -138,6 +139,14 @@ class ScalarExprLowering {
     return builder.createBool(getLoc(), value);
   }
 
+  /// Generate a real constant with a value `value`.
+  template <int KIND>
+  mlir::Value genRealConstant(mlir::MLIRContext *context,
+                              const llvm::APFloat &value) {
+    mlir::Type fltTy = Fortran::lower::convertReal(context, KIND);
+    return builder.createRealConstant(getLoc(), fltTy, value);
+  }
+
   /// Returns a reference to a symbol or its box/boxChar descriptor if it has
   /// one.
   ExtValue gen(Fortran::semantics::SymbolRef sym) {
@@ -350,7 +359,27 @@ class ScalarExprLowering {
     } else if constexpr (TC == Fortran::common::TypeCategory::Logical) {
       return genBoolConstant(value.IsTrue());
     } else if constexpr (TC == Fortran::common::TypeCategory::Real) {
-      TODO(getLoc(), "genval real constant");
+      std::string str = value.DumpHexadecimal();
+      if constexpr (KIND == 2) {
+        llvm::APFloat floatVal{llvm::APFloatBase::IEEEhalf(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      } else if constexpr (KIND == 3) {
+        llvm::APFloat floatVal{llvm::APFloatBase::BFloat(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      } else if constexpr (KIND == 4) {
+        llvm::APFloat floatVal{llvm::APFloatBase::IEEEsingle(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      } else if constexpr (KIND == 10) {
+        llvm::APFloat floatVal{llvm::APFloatBase::x87DoubleExtended(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      } else if constexpr (KIND == 16) {
+        llvm::APFloat floatVal{llvm::APFloatBase::IEEEquad(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      } else {
+        // convert everything else to double
+        llvm::APFloat floatVal{llvm::APFloatBase::IEEEdouble(), str};
+        return genRealConstant<KIND>(builder.getContext(), floatVal);
+      }
     } else if constexpr (TC == Fortran::common::TypeCategory::Complex) {
       TODO(getLoc(), "genval complex constant");
     } else /*constexpr*/ {

diff  --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 39424d3ff0b0a..429fae81e25cc 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -520,7 +520,7 @@ mlir::Type Fortran::lower::translateVariableToFIRType(
 }
 
 mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) {
-  return genFIRType<Fortran::common::TypeCategory::Real>(context, kind);
+  return genRealType(context, kind);
 }
 
 mlir::Type Fortran::lower::getSequenceRefType(mlir::Type refType) {

diff  --git a/flang/test/Lower/assignment.f90 b/flang/test/Lower/assignment.f90
index ce9689a708a8f..26aa33631d0e4 100644
--- a/flang/test/Lower/assignment.f90
+++ b/flang/test/Lower/assignment.f90
@@ -255,3 +255,32 @@ real function divf(a, b)
 ! CHECK:         fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         return %[[RET]] : !fir.complex<4>
+
+subroutine real_constant()
+  real(2) :: a
+  real(4) :: b
+  real(8) :: c
+  real(10) :: d
+  real(16) :: e
+  a = 2.0_2
+  b = 4.0_4
+  c = 8.0_8
+  d = 10.0_10
+  e = 16.0_16
+end
+
+! CHECK: %[[A:.*]] = fir.alloca f16
+! CHECK: %[[B:.*]] = fir.alloca f32
+! CHECK: %[[C:.*]] = fir.alloca f64
+! CHECK: %[[D:.*]] = fir.alloca f80
+! CHECK: %[[E:.*]] = fir.alloca f128
+! CHECK: %[[C2:.*]] = arith.constant 2.000000e+00 : f16
+! CHECK: fir.store %[[C2]] to %[[A]] : !fir.ref<f16>
+! CHECK: %[[C4:.*]] = arith.constant 4.000000e+00 : f32
+! CHECK: fir.store %[[C4]] to %[[B]] : !fir.ref<f32>
+! CHECK: %[[C8:.*]] = arith.constant 8.000000e+00 : f64
+! CHECK: fir.store %[[C8]] to %[[C]] : !fir.ref<f64>
+! CHECK: %[[C10:.*]] = arith.constant 1.000000e+01 : f80
+! CHECK: fir.store %[[C10]] to %[[D]] : !fir.ref<f80>
+! CHECK: %[[C16:.*]] = arith.constant 1.600000e+01 : f128
+! CHECK: fir.store %[[C16]] to %[[E]] : !fir.ref<f128>


        


More information about the flang-commits mailing list