[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