Skip to content

Commit

Permalink
[flang] Lower F08 merge_bits intrinsic.
Browse files Browse the repository at this point in the history
Lower F08 merge_bits intrinsic.

Differential Revision: https://reviews.llvm.org/D129779
  • Loading branch information
Tarun Prabhu committed Jul 21, 2022
1 parent 297ba16 commit b6fef08
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
20 changes: 20 additions & 0 deletions flang/lib/Lower/IntrinsicCall.cpp
Expand Up @@ -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>);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
110 changes: 110 additions & 0 deletions flang/test/Lower/Intrinsics/merge_bits.f90
@@ -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

0 comments on commit b6fef08

Please sign in to comment.