[flang-commits] [flang] be6e84e - [flang][lowering] Add support for lowering of the `ibits` intrinsic

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Tue Mar 15 09:33:42 PDT 2022


Author: Andrzej Warzynski
Date: 2022-03-15T16:33:13Z
New Revision: be6e84e2520be128effbdde2f3d6c53a7e0daf3e

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

LOG: [flang][lowering] Add support for lowering of the `ibits` intrinsic

This patch adds support for lowering of the `ibits` 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

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

Co-authored-by: Jean Perier <jperier at nvidia.com>
Co-authored-by: Valentin Clement <clementval at gmail.com>
Co-authored-by: V Donaldson <vdonaldson at nvidia.com>

Added: 
    flang/test/Lower/Intrinsics/ibits.f90

Modified: 
    flang/lib/Lower/IntrinsicCall.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index e43f3a3a5fb15..f8bc373ddcb8c 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -275,6 +275,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 genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -387,6 +388,7 @@ static constexpr IntrinsicHandler handlers[]{
      {{{"vector_a", asBox}, {"vector_b", asBox}}},
      /*isElemental=*/false},
     {"iand", &I::genIand},
+    {"ibits", &I::genIbits},
     {"min", &I::genExtremum<Extremum::Min, ExtremumBehavior::MinMaxss>},
     {"sum",
      &I::genSum,
@@ -1295,6 +1297,33 @@ mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
   return builder.create<mlir::arith::AndIOp>(loc, args[0], args[1]);
 }
 
+// IBITS
+mlir::Value IntrinsicLibrary::genIbits(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  // A conformant IBITS(I,POS,LEN) call satisfies:
+  //     POS >= 0
+  //     LEN >= 0
+  //     POS + LEN <= BIT_SIZE(I)
+  // Return:  LEN == 0 ? 0 : (I >> POS) & (-1 >> (BIT_SIZE(I) - LEN))
+  // For a conformant call, implementing (I >> POS) with a signed or an
+  // unsigned shift produces the same result.  For a nonconformant call,
+  // the two choices may produce 
diff erent results.
+  assert(args.size() == 3);
+  mlir::Value pos = builder.createConvert(loc, resultType, args[1]);
+  mlir::Value len = builder.createConvert(loc, resultType, args[2]);
+  mlir::Value bitSize = builder.createIntegerConstant(
+      loc, resultType, resultType.cast<mlir::IntegerType>().getWidth());
+  auto shiftCount = builder.create<mlir::arith::SubIOp>(loc, bitSize, len);
+  mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0);
+  mlir::Value ones = builder.createIntegerConstant(loc, resultType, -1);
+  auto mask = builder.create<mlir::arith::ShRUIOp>(loc, ones, shiftCount);
+  auto res1 = builder.create<mlir::arith::ShRSIOp>(loc, args[0], pos);
+  auto res2 = builder.create<mlir::arith::AndIOp>(loc, res1, mask);
+  auto lenIsZero = builder.create<mlir::arith::CmpIOp>(
+      loc, mlir::arith::CmpIPredicate::eq, len, zero);
+  return builder.create<mlir::arith::SelectOp>(loc, lenIsZero, zero, res2);
+}
+
 // Compare two FIR values and return boolean result as i1.
 template <Extremum extremum, ExtremumBehavior behavior>
 static mlir::Value createExtremumCompare(mlir::Location loc,

diff  --git a/flang/test/Lower/Intrinsics/ibits.f90 b/flang/test/Lower/Intrinsics/ibits.f90
new file mode 100644
index 0000000000000..9702aa346d663
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/ibits.f90
@@ -0,0 +1,23 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: ibits_test
+function ibits_test(i, j, k)
+  ! CHECK-DAG: %[[result:.*]] = fir.alloca i32 {bindc_name = "ibits_test"
+  ! CHECK-DAG: %[[i:.*]] = fir.load %arg0 : !fir.ref<i32>
+  ! CHECK-DAG: %[[j:.*]] = fir.load %arg1 : !fir.ref<i32>
+  ! CHECK-DAG: %[[k:.*]] = fir.load %arg2 : !fir.ref<i32>
+  ! CHECK-DAG: %[[VAL_7:.*]] = arith.constant 32 : i32
+  ! CHECK-DAG: %[[VAL_8:.*]] = arith.subi %[[VAL_7]], %[[k]] : i32
+  ! CHECK-DAG: %[[VAL_9:.*]] = arith.constant 0 : i32
+  ! CHECK-DAG: %[[VAL_10:.*]] = arith.constant -1 : i32
+  ! CHECK: %[[VAL_11:.*]] = arith.shrui %[[VAL_10]], %[[VAL_8]] : i32
+  ! CHECK: %[[VAL_12:.*]] = arith.shrsi %[[i]], %[[j]] : i32
+  ! CHECK: %[[VAL_13:.*]] = arith.andi %[[VAL_12]], %[[VAL_11]] : i32
+  ! CHECK: %[[VAL_14:.*]] = arith.cmpi eq, %[[k]], %[[VAL_9]] : i32
+  ! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_14]], %[[VAL_9]], %[[VAL_13]] : i32
+  ! CHECK: fir.store %[[VAL_15]] to %[[result]] : !fir.ref<i32>
+  ! CHECK: %[[VAL_16:.*]] = fir.load %[[result]] : !fir.ref<i32>
+  ! CHECK: return %[[VAL_16]] : i32
+  ibits_test = ibits(i, j, k)
+end


        


More information about the flang-commits mailing list