forked from OSchip/llvm-project
[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@nvidia.com> Co-authored-by: Valentin Clement <clementval@gmail.com> Co-authored-by: V Donaldson <vdonaldson@nvidia.com>
This commit is contained in:
parent
b783e5c203
commit
be6e84e252
|
@ -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 different 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,
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue