[flang-commits] [flang] 51cf471 - [flang] Lower misc intrinsics

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Thu Mar 17 05:22:00 PDT 2022


Author: Valentin Clement
Date: 2022-03-17T13:21:53+01:00
New Revision: 51cf471dc1550b12711e22e13378ef891660a84e

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

LOG: [flang] Lower misc intrinsics

This patch adds lowering for couple of intrinsics:
- `btest`
- `ceiling`
- `nearest`
- `scale`

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

Reviewed By: jeanPerier

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

Co-authored-by: Jean Perier <jperier at nvidia.com>
Co-authored-by: V Donaldson <vdonaldson at nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Co-authored-by: AlexisPerry <aperry at lanl.gov>

Added: 
    flang/test/Lower/Intrinsics/btest.f90
    flang/test/Lower/Intrinsics/ceiling.f90
    flang/test/Lower/Intrinsics/nearest.f90
    flang/test/Lower/Intrinsics/scale.f90

Modified: 
    flang/lib/Lower/IntrinsicCall.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index 404a9acae97ff..8039cef87a625 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -442,6 +442,8 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genAny(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genAssociated(mlir::Type,
                                    llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   template <mlir::arith::CmpIPredicate pred>
@@ -481,6 +483,7 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genMinval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -491,6 +494,7 @@ struct IntrinsicLibrary {
   void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
   void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genReshape(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genSetExponent(mlir::Type resultType,
                              llvm::ArrayRef<mlir::Value> args);
@@ -623,6 +627,8 @@ static constexpr IntrinsicHandler handlers[]{
      &I::genAssociated,
      {{{"pointer", asInquired}, {"target", asInquired}}},
      /*isElemental=*/false},
+    {"btest", &I::genBtest},
+    {"ceiling", &I::genCeiling},
     {"char", &I::genChar},
     {"count",
      &I::genCount,
@@ -718,6 +724,7 @@ static constexpr IntrinsicHandler handlers[]{
      /*isElemental=*/false},
     {"mod", &I::genMod},
     {"modulo", &I::genModulo},
+    {"nearest", &I::genNearest},
     {"nint", &I::genNint},
     {"not", &I::genNot},
     {"null", &I::genNull, {{{"mold", asInquired}}}, /*isElemental=*/false},
@@ -756,6 +763,10 @@ static constexpr IntrinsicHandler handlers[]{
        {"pad", asBox, handleDynamicOptional},
        {"order", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
+    {"scale",
+     &I::genScale,
+     {{{"x", asValue}, {"i", asValue}}},
+     /*isElemental=*/true},
     {"scan",
      &I::genScan,
      {{{"string", asAddr},
@@ -896,6 +907,9 @@ static mlir::FunctionType genIntF32FuncType(mlir::MLIRContext *context) {
 static constexpr RuntimeFunction llvmIntrinsics[] = {
     {"abs", "llvm.fabs.f32", genF32F32FuncType},
     {"abs", "llvm.fabs.f64", genF64F64FuncType},
+    // ceil is used for CEILING but is 
diff erent, it returns a real.
+    {"ceil", "llvm.ceil.f32", genF32F32FuncType},
+    {"ceil", "llvm.ceil.f64", genF64F64FuncType},
     // llvm.floor is used for FLOOR, but returns real.
     {"floor", "llvm.floor.f32", genF32F32FuncType},
     {"floor", "llvm.floor.f64", genF64F64FuncType},
@@ -1769,6 +1783,35 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType,
   return Fortran::lower::genAssociated(builder, loc, pointerBox, targetBox);
 }
 
+// BTEST
+mlir::Value IntrinsicLibrary::genBtest(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  // A conformant BTEST(I,POS) call satisfies:
+  //     POS >= 0
+  //     POS < BIT_SIZE(I)
+  // Return:  (I >> POS) & 1
+  assert(args.size() == 2);
+  mlir::Type argType = args[0].getType();
+  mlir::Value pos = builder.createConvert(loc, argType, args[1]);
+  auto shift = builder.create<mlir::arith::ShRUIOp>(loc, args[0], pos);
+  mlir::Value one = builder.createIntegerConstant(loc, argType, 1);
+  auto res = builder.create<mlir::arith::AndIOp>(loc, shift, one);
+  return builder.createConvert(loc, resultType, res);
+}
+
+// CEILING
+mlir::Value IntrinsicLibrary::genCeiling(mlir::Type resultType,
+                                         llvm::ArrayRef<mlir::Value> args) {
+  // Optional KIND argument.
+  assert(args.size() >= 1);
+  mlir::Value arg = args[0];
+  // Use ceil that is not an actual Fortran intrinsic but that is
+  // an llvm intrinsic that does the same, but return a floating
+  // point.
+  mlir::Value ceil = genRuntimeCall("ceil", arg.getType(), {arg});
+  return builder.createConvert(loc, resultType, ceil);
+}
+
 // CHAR
 fir::ExtendedValue
 IntrinsicLibrary::genChar(mlir::Type type,
@@ -2502,6 +2545,18 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType,
                                                remainder);
 }
 
+// NEAREST
+mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType,
+                                         llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 2);
+
+  mlir::Value realX = fir::getBase(args[0]);
+  mlir::Value realS = fir::getBase(args[1]);
+
+  return builder.createConvert(
+      loc, resultType, fir::runtime::genNearest(builder, loc, realX, realS));
+}
+
 // NINT
 mlir::Value IntrinsicLibrary::genNint(mlir::Type resultType,
                                       llvm::ArrayRef<mlir::Value> args) {
@@ -2657,6 +2712,18 @@ IntrinsicLibrary::genReshape(mlir::Type resultType,
                            "unexpected result for RESHAPE");
 }
 
+// SCALE
+mlir::Value IntrinsicLibrary::genScale(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 2);
+
+  mlir::Value realX = fir::getBase(args[0]);
+  mlir::Value intI = fir::getBase(args[1]);
+
+  return builder.createConvert(
+      loc, resultType, fir::runtime::genScale(builder, loc, realX, intI));
+}
+
 // SCAN
 fir::ExtendedValue
 IntrinsicLibrary::genScan(mlir::Type resultType,

diff  --git a/flang/test/Lower/Intrinsics/btest.f90 b/flang/test/Lower/Intrinsics/btest.f90
new file mode 100644
index 0000000000000..a2bf7f56a6214
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/btest.f90
@@ -0,0 +1,18 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: btest_test
+function btest_test(i, j)
+    logical btest_test
+    ! CHECK-DAG: %[[result:[0-9]+]] = fir.alloca !fir.logical<4> {bindc_name = "btest_test"
+    ! CHECK-DAG: %[[i:[0-9]+]] = fir.load %arg0 : !fir.ref<i32>
+    ! CHECK-DAG: %[[j:[0-9]+]] = fir.load %arg1 : !fir.ref<i32>
+    ! CHECK-DAG: %[[VAL_5:.*]] = arith.shrui %[[i]], %[[j]] : i32
+    ! CHECK-DAG: %[[VAL_6:.*]] = arith.constant 1 : i32
+    ! CHECK: %[[VAL_7:.*]] = arith.andi %[[VAL_5]], %[[VAL_6]] : i32
+    ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> !fir.logical<4>
+    ! CHECK: fir.store %[[VAL_8]] to %[[result]] : !fir.ref<!fir.logical<4>>
+    ! CHECK: %[[VAL_9:.*]] = fir.load %[[result]] : !fir.ref<!fir.logical<4>>
+    ! CHECK: return %[[VAL_9]] : !fir.logical<4>
+    btest_test = btest(i, j)
+  end
+  
\ No newline at end of file

diff  --git a/flang/test/Lower/Intrinsics/ceiling.f90 b/flang/test/Lower/Intrinsics/ceiling.f90
new file mode 100644
index 0000000000000..11a91c863a596
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/ceiling.f90
@@ -0,0 +1,20 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: ceiling_test1
+subroutine ceiling_test1(i, a)
+    integer :: i
+    real :: a
+    i = ceiling(a)
+    ! CHECK: %[[f:.*]] = fir.call @llvm.ceil.f32
+    ! CHECK: fir.convert %[[f]] : (f32) -> i32
+  end subroutine
+  ! CHECK-LABEL: ceiling_test2
+  subroutine ceiling_test2(i, a)
+    integer(8) :: i
+    real :: a
+    i = ceiling(a, 8)
+    ! CHECK: %[[f:.*]] = fir.call @llvm.ceil.f32
+    ! CHECK: fir.convert %[[f]] : (f32) -> i64
+  end subroutine
+  
+  
\ No newline at end of file

diff  --git a/flang/test/Lower/Intrinsics/nearest.f90 b/flang/test/Lower/Intrinsics/nearest.f90
new file mode 100644
index 0000000000000..0c32b78115919
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/nearest.f90
@@ -0,0 +1,72 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: nearest_test1
+subroutine nearest_test1(x, s)
+    real :: x, s, res
+  ! CHECK: %[[res:.*]] = fir.alloca f32 {bindc_name = "res", uniq_name = "_QFnearest_test1Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f32>
+  ! CHECK: %[[s:.*]] = fir.load %arg1 : !fir.ref<f32>
+  ! CHECK: %[[zero:.*]] = arith.constant 0.000000e+00 : f32
+  ! CHECK: %[[cmp:.*]] = arith.cmpf ogt, %[[s]], %[[zero]] : f32
+  ! CHECK: %[[pos:.*]] = arith.select %[[cmp]], %true, %false : i1
+    res = nearest(x, s)
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranANearest4(%[[x]], %[[pos]]) : (f32, i1) -> f32
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f32>
+  end subroutine nearest_test1
+  
+  ! CHECK-LABEL: nearest_test2
+  subroutine nearest_test2(x, s)
+    real(kind=8) :: x, s, res
+  ! CHECK: %[[res:.*]] = fir.alloca f64 {bindc_name = "res", uniq_name = "_QFnearest_test2Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f64>
+  ! CHECK: %[[s:.*]] = fir.load %arg1 : !fir.ref<f64>
+  ! CHECK: %[[zero:.*]] = arith.constant 0.000000e+00 : f64
+  ! CHECK: %[[cmp:.*]] = arith.cmpf ogt, %[[s]], %[[zero]] : f64
+  ! CHECK: %[[pos:.*]] = arith.select %[[cmp]], %true, %false : i1
+    res = nearest(x, s)
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranANearest8(%[[x]], %[[pos]]) : (f64, i1) -> f64
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f64>
+  end subroutine nearest_test2
+  
+  ! CHECK-LABEL: nearest_test3
+  subroutine nearest_test3(x, s)
+    real(kind=10) :: x, s, res
+  ! CHECK: %[[res:.*]] = fir.alloca f80 {bindc_name = "res", uniq_name = "_QFnearest_test3Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f80>
+  ! CHECK: %[[s:.*]] = fir.load %arg1 : !fir.ref<f80>
+  ! CHECK: %[[zero:.*]] = arith.constant 0.000000e+00 : f80
+  ! CHECK: %[[cmp:.*]] = arith.cmpf ogt, %[[s]], %[[zero]] : f80
+  ! CHECK: %[[pos:.*]] = arith.select %[[cmp]], %true, %false : i1
+    res = nearest(x, s)
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranANearest10(%[[x]], %[[pos]]) : (f80, i1) -> f80
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f80>
+  end subroutine nearest_test3
+  
+  ! CHECK-LABEL: nearest_test4
+  subroutine nearest_test4(x, s)
+    real(kind=16) :: x, s, res
+  ! CHECK: %[[res:.*]] = fir.alloca f128 {bindc_name = "res", uniq_name = "_QFnearest_test4Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f128>
+  ! CHECK: %[[s:.*]] = fir.load %arg1 : !fir.ref<f128>
+  ! CHECK: %[[zero:.*]] = arith.constant 0.000000e+00 : f128
+  ! CHECK: %[[cmp:.*]] = arith.cmpf ogt, %[[s]], %[[zero]] : f128
+  ! CHECK: %[[pos:.*]] = arith.select %[[cmp]], %true, %false : i1
+    res = nearest(x, s)
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranANearest16(%[[x]], %[[pos]]) : (f128, i1) -> f128
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f128>
+  end subroutine nearest_test4
+  
+  ! CHECK-LABEL: nearest_test5
+  subroutine nearest_test5(x, s)
+    real(kind=16) :: x, res
+  ! CHECK: %[[res:.*]] = fir.alloca f128 {bindc_name = "res", uniq_name = "_QFnearest_test5Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f128>
+    real :: s
+  ! CHECK: %[[s:.*]] = fir.load %arg1 : !fir.ref<f32>
+  ! CHECK: %[[zero:.*]] = arith.constant 0.000000e+00 : f32
+  ! CHECK: %[[cmp:.*]] = arith.cmpf ogt, %[[s]], %[[zero]] : f32
+  ! CHECK: %[[pos:.*]] = arith.select %[[cmp]], %true, %false : i1
+    res = nearest(x, s)
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranANearest16(%[[x]], %[[pos]]) : (f128, i1) -> f128
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f128>
+  end subroutine nearest_test5

diff  --git a/flang/test/Lower/Intrinsics/scale.f90 b/flang/test/Lower/Intrinsics/scale.f90
new file mode 100644
index 0000000000000..7afb2843f5721
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/scale.f90
@@ -0,0 +1,53 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: scale_test1
+subroutine scale_test1(x, i)
+    real :: x, res
+  ! CHECK: %[[res:.*]] = fir.alloca f32 {bindc_name = "res", uniq_name = "_QFscale_test1Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f32>
+    integer :: i
+  ! CHECK: %[[i0:.*]] = fir.load %arg1 : !fir.ref<i32>
+    res = scale(x, i)
+  ! CHECK: %[[i1:.*]] = fir.convert %[[i0]] : (i32) -> i64
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranAScale4(%[[x]], %[[i1]]) : (f32, i64) -> f32
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f32>
+  end subroutine scale_test1
+  
+  ! CHECK-LABEL: scale_test2
+  subroutine scale_test2(x, i)
+    real(kind=8) :: x, res
+  ! CHECK: %[[res:.*]] = fir.alloca f64 {bindc_name = "res", uniq_name = "_QFscale_test2Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f64>
+    integer :: i
+  ! CHECK: %[[i0:.*]] = fir.load %arg1 : !fir.ref<i32>
+    res = scale(x, i)
+  ! CHECK: %[[i1:.*]] = fir.convert %[[i0]] : (i32) -> i64
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranAScale8(%[[x]], %[[i1]]) : (f64, i64) -> f64
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f64>
+  end subroutine scale_test2
+  
+  ! CHECK-LABEL: scale_test3
+  subroutine scale_test3(x, i)
+    real(kind=10) :: x, res
+  ! CHECK: %[[res:.*]] = fir.alloca f80 {bindc_name = "res", uniq_name = "_QFscale_test3Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f80>
+    integer :: i
+  ! CHECK: %[[i0:.*]] = fir.load %arg1 : !fir.ref<i32>
+    res = scale(x, i)
+  ! CHECK: %[[i1:.*]] = fir.convert %[[i0]] : (i32) -> i64
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranAScale10(%[[x]], %[[i1]]) : (f80, i64) -> f80
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f80>
+  end subroutine scale_test3
+  
+  ! CHECK-LABEL: scale_test4
+  subroutine scale_test4(x, i)
+    real(kind=16) :: x, res
+  ! CHECK: %[[res:.*]] = fir.alloca f128 {bindc_name = "res", uniq_name = "_QFscale_test4Eres"}
+  ! CHECK: %[[x:.*]] = fir.load %arg0 : !fir.ref<f128>
+    integer :: i
+  ! CHECK: %[[i0:.*]] = fir.load %arg1 : !fir.ref<i32>
+    res = scale(x, i)
+  ! CHECK: %[[i1:.*]] = fir.convert %[[i0]] : (i32) -> i64
+  ! CHECK: %[[tmp:.*]] = fir.call @_FortranAScale16(%[[x]], %[[i1]]) : (f128, i64) -> f128
+  ! CHECK: fir.store %[[tmp]] to %[[res]] : !fir.ref<f128>
+  end subroutine scale_test4


        


More information about the flang-commits mailing list