[flang][lowering] Add support for lowering of the `ibclr` intrinsic
authorAndrzej Warzynski <andrzej.warzynski@arm.com>
Wed, 16 Mar 2022 10:56:38 +0000 (10:56 +0000)
committerAndrzej Warzynski <andrzej.warzynski@arm.com>
Wed, 16 Mar 2022 17:05:01 +0000 (17:05 +0000)
This patch adds support for lowering of the `ibclr` intrinsic from Fortran
to the FIR dialect of MLIR.

This is part of the upstreaming effort from the `fir-dev` branch in [1].

[1] https://github.com/flang-compiler/f18-llvm-project

Co-authored-by: V Donaldson <vdonaldson@nvidia.com>
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Valentin Clement <clementval@gmail.com>
Differential Revision: https://reviews.llvm.org/D121789

flang/lib/Lower/IntrinsicCall.cpp
flang/test/Lower/Intrinsics/ibclr.f90 [new file with mode: 0644]

index b6a8ddd..44d59fb 100644 (file)
@@ -457,6 +457,7 @@ struct IntrinsicLibrary {
   /// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments
   /// in the llvm::ArrayRef.
   mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -634,6 +635,7 @@ static constexpr IntrinsicHandler handlers[]{
        {"dim", asValue}}},
      /*isElemental=*/false},
     {"iand", &I::genIand},
+    {"ibclr", &I::genIbclr},
     {"ibits", &I::genIbits},
     {"ibset", &I::genIbset},
     {"ieor", &I::genIeor},
@@ -1891,6 +1893,22 @@ mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
   return builder.create<mlir::arith::AndIOp>(loc, args[0], args[1]);
 }
 
+// IBCLR
+mlir::Value IntrinsicLibrary::genIbclr(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  // A conformant IBCLR(I,POS) call satisfies:
+  //     POS >= 0
+  //     POS < BIT_SIZE(I)
+  // Return:  I & (!(1 << POS))
+  assert(args.size() == 2);
+  mlir::Value pos = builder.createConvert(loc, resultType, args[1]);
+  mlir::Value one = builder.createIntegerConstant(loc, resultType, 1);
+  mlir::Value ones = builder.createIntegerConstant(loc, resultType, -1);
+  auto mask = builder.create<mlir::arith::ShLIOp>(loc, one, pos);
+  auto res = builder.create<mlir::arith::XOrIOp>(loc, ones, mask);
+  return builder.create<mlir::arith::AndIOp>(loc, args[0], res);
+}
+
 // IBITS
 mlir::Value IntrinsicLibrary::genIbits(mlir::Type resultType,
                                        llvm::ArrayRef<mlir::Value> args) {
diff --git a/flang/test/Lower/Intrinsics/ibclr.f90 b/flang/test/Lower/Intrinsics/ibclr.f90
new file mode 100644 (file)
index 0000000..ec30b25
--- /dev/null
@@ -0,0 +1,19 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: ibclr_test
+function ibclr_test(i, j)
+  ! CHECK-DAG: %[[result:.*]] = fir.alloca i32 {bindc_name = "ibclr_test"
+  ! CHECK-DAG: %[[i:.*]] = fir.load %arg0 : !fir.ref<i32>
+  ! CHECK-DAG: %[[j:.*]] = fir.load %arg1 : !fir.ref<i32>
+  ! CHECK-DAG: %[[VAL_5:.*]] = arith.constant 1 : i32
+  ! CHECK-DAG: %[[VAL_6:.*]] = arith.constant -1 : i32
+  ! CHECK: %[[VAL_7:.*]] = arith.shli %[[VAL_5]], %[[j]] : i32
+  ! CHECK: %[[VAL_8:.*]] = arith.xori %[[VAL_6]], %[[VAL_7]] : i32
+  ! CHECK: %[[VAL_9:.*]] = arith.andi %[[i]], %[[VAL_8]] : i32
+  ! CHECK: fir.store %[[VAL_9]] to %[[result]] : !fir.ref<i32>
+  ! CHECK: %[[VAL_10:.*]] = fir.load %[[result]] : !fir.ref<i32>
+  ! CHECK: return %[[VAL_10]] : i32
+  ibclr_test = ibclr(i, j)
+end
+