[flang] Lower F08 merge_bits intrinsic.
authorTarun Prabhu <tarun.prabhu@gmail.com>
Thu, 21 Jul 2022 16:39:54 +0000 (10:39 -0600)
committerTarun Prabhu <tarun.prabhu@gmail.com>
Thu, 21 Jul 2022 16:42:25 +0000 (10:42 -0600)
Lower F08 merge_bits intrinsic.

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

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

index 6167b28..7d8aac5 100644 (file)
@@ -516,6 +516,7 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genMaxloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMaxval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMerge(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genMergeBits(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genMinloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMinval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -821,6 +822,7 @@ static constexpr IntrinsicHandler handlers[]{
        {"mask", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
     {"merge", &I::genMerge},
+    {"merge_bits", &I::genMergeBits},
     {"min", &I::genExtremum<Extremum::Min, ExtremumBehavior::MinMaxss>},
     {"minloc",
      &I::genMinloc,
@@ -3292,6 +3294,24 @@ IntrinsicLibrary::genMerge(mlir::Type,
   return rslt;
 }
 
+// MERGE_BITS
+mlir::Value IntrinsicLibrary::genMergeBits(mlir::Type resultType,
+                                           llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 3);
+
+  mlir::Value i = builder.createConvert(loc, resultType, args[0]);
+  mlir::Value j = builder.createConvert(loc, resultType, args[1]);
+  mlir::Value mask = builder.createConvert(loc, resultType, args[2]);
+  mlir::Value ones = builder.createIntegerConstant(loc, resultType, -1);
+
+  // MERGE_BITS(I, J, MASK) = IOR(IAND(I, MASK), IAND(J, NOT(MASK)))
+  mlir::Value notMask = builder.create<mlir::arith::XOrIOp>(loc, mask, ones);
+  mlir::Value lft = builder.create<mlir::arith::AndIOp>(loc, i, mask);
+  mlir::Value rgt = builder.create<mlir::arith::AndIOp>(loc, j, notMask);
+
+  return builder.create<mlir::arith::OrIOp>(loc, lft, rgt);
+}
+
 // MOD
 mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType,
                                      llvm::ArrayRef<mlir::Value> args) {
diff --git a/flang/test/Lower/Intrinsics/merge_bits.f90 b/flang/test/Lower/Intrinsics/merge_bits.f90
new file mode 100644 (file)
index 0000000..b5c2745
--- /dev/null
@@ -0,0 +1,110 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: merge_bits1_test
+! CHECK-SAME: %[[IREF:.*]]: !fir.ref<i8>{{.*}}, %[[JREF:.*]]: !fir.ref<i8>{{.*}}, %[[MREF:.*]]: !fir.ref<i8>{{.*}}, %[[RREF:.*]]: !fir.ref<i8>{{.*}}
+subroutine merge_bits1_test(i, j, m, r)
+  integer(1) :: i, j, m
+  integer(1) :: r
+
+  ! CHECK: %[[I:.*]] = fir.load %[[IREF]] : !fir.ref<i8>
+  ! CHECK: %[[J:.*]] = fir.load %[[JREF]] : !fir.ref<i8>
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i8>
+  r = merge_bits(i, j, m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i8
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i8
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i8
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i8
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i8
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i8>
+end subroutine merge_bits1_test
+
+! CHECK-LABEL: merge_bits2_test
+! CHECK-SAME: %[[IREF:.*]]: !fir.ref<i16>{{.*}}, %[[JREF:.*]]: !fir.ref<i16>{{.*}}, %[[MREF:.*]]: !fir.ref<i16>{{.*}}, %[[RREF:.*]]: !fir.ref<i16>{{.*}}
+subroutine merge_bits2_test(i, j, m, r)
+  integer(2) :: i, j, m
+  integer(2) :: r
+
+  ! CHECK: %[[I:.*]] = fir.load %[[IREF]] : !fir.ref<i16>
+  ! CHECK: %[[J:.*]] = fir.load %[[JREF]] : !fir.ref<i16>
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i16>
+  r = merge_bits(i, j, m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i16
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i16
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i16
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i16
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i16
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i16>
+end subroutine merge_bits2_test
+
+! CHECK-LABEL: merge_bits4_test
+! CHECK-SAME: %[[IREF:.*]]: !fir.ref<i32>{{.*}}, %[[JREF:.*]]: !fir.ref<i32>{{.*}}, %[[MREF:.*]]: !fir.ref<i32>{{.*}}, %[[RREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine merge_bits4_test(i, j, m, r)
+  integer(4) :: i, j, m
+  integer(4) :: r
+
+  ! CHECK: %[[I:.*]] = fir.load %[[IREF]] : !fir.ref<i32>
+  ! CHECK: %[[J:.*]] = fir.load %[[JREF]] : !fir.ref<i32>
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i32>
+  r = merge_bits(i, j, m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i32
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i32
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i32
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i32
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i32>
+end subroutine merge_bits4_test
+
+! CHECK-LABEL: merge_bits8_test
+! CHECK-SAME: %[[IREF:.*]]: !fir.ref<i64>{{.*}}, %[[JREF:.*]]: !fir.ref<i64>{{.*}}, %[[MREF:.*]]: !fir.ref<i64>{{.*}}, %[[RREF:.*]]: !fir.ref<i64>{{.*}}
+subroutine merge_bits8_test(i, j, m, r)
+  integer(8) :: i, j, m
+  integer(8) :: r
+
+  ! CHECK: %[[I:.*]] = fir.load %[[IREF]] : !fir.ref<i64>
+  ! CHECK: %[[J:.*]] = fir.load %[[JREF]] : !fir.ref<i64>
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i64>
+  r = merge_bits(i, j, m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i64
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i64
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i64
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i64
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i64
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i64>
+end subroutine merge_bits8_test
+
+! CHECK-LABEL: merge_bitsz0_test
+! CHECK-SAME: %[[JREF:.*]]: !fir.ref<i32>{{.*}}, %[[MREF:.*]]: !fir.ref<i32>{{.*}}, %[[RREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine merge_bitsz0_test(j, m, r)
+  integer :: j, m
+  integer :: r
+
+  ! CHECK: %[[I:.*]] = arith.constant 13 : i32
+  ! CHECK: %[[J:.*]] = fir.load %[[JREF]] : !fir.ref<i32>
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i32>
+  r = merge_bits(B'1101', j, m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i32
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i32
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i32
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i32
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i32>
+end subroutine merge_bitsz0_test
+
+! CHECK-LABEL: merge_bitsz1_test
+! CHECK-SAME: %[[IREF:.*]]: !fir.ref<i32>{{.*}}, %[[MREF:.*]]: !fir.ref<i32>{{.*}}, %[[RREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine merge_bitsz1_test(i, m, r)
+  integer :: i, m
+  integer :: r
+
+  ! CHECK: %[[I:.*]] = fir.load %[[IREF]] : !fir.ref<i32>
+  ! CHECK: %[[J:.*]] = arith.constant 13 : i32
+  ! CHECK: %[[M:.*]] = fir.load %[[MREF]] : !fir.ref<i32>
+  r = merge_bits(i, Z'0D', m)
+  ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32
+  ! CHECK: %[[NM:.*]] = arith.xori %[[M]], %[[C__1]] : i32
+  ! CHECK: %[[LFT:.*]] = arith.andi %[[I]], %[[M]] : i32
+  ! CHECK: %[[RGT:.*]] = arith.andi %[[J]], %[[NM]] : i32
+  ! CHECK: %[[RES:.*]] = arith.ori %[[LFT]], %[[RGT]] : i32
+  ! CHECK: fir.store %[[RES]] to %[[RREF]] : !fir.ref<i32>
+end subroutine merge_bitsz1_test