diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -3297,6 +3297,7 @@ llvm::ArrayRef args) { assert(args.size() == 2); + mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); mlir::Value ones = builder.createIntegerConstant(loc, resultType, -1); mlir::Value bitSize = builder.createIntegerConstant( loc, resultType, resultType.getIntOrFloatBitWidth()); @@ -3309,7 +3310,11 @@ // in this case either, so we choose the most efficient implementation. mlir::Value shift = builder.create(loc, bitSize, bitsToSet); - return builder.create(loc, ones, shift); + mlir::Value shifted = builder.create(loc, ones, shift); + mlir::Value isZero = builder.create( + loc, mlir::arith::CmpIPredicate::eq, bitsToSet, zero); + + return builder.create(loc, isZero, zero, shifted); } // MATMUL diff --git a/flang/test/Lower/Intrinsics/maskl.f90 b/flang/test/Lower/Intrinsics/maskl.f90 --- a/flang/test/Lower/Intrinsics/maskl.f90 +++ b/flang/test/Lower/Intrinsics/maskl.f90 @@ -9,11 +9,14 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskl(a) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i32 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32 ! CHECK: %[[BITS:.*]] = arith.constant 32 : i32 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_VAL]] : i32 ! CHECK: %[[SHIFT:.*]] = arith.shli %[[C__1]], %[[LEN]] : i32 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_VAL]], %[[C__0]] : i32 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskl_test ! CHECK-LABEL: maskl1_test @@ -24,12 +27,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskl(a, 1) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i8 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i8 ! CHECK: %[[BITS:.*]] = arith.constant 8 : i8 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i8 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i8 ! CHECK: %[[SHIFT:.*]] = arith.shli %[[C__1]], %[[LEN]] : i8 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i8 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i8 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskl1_test ! CHECK-LABEL: maskl2_test @@ -40,12 +46,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskl(a, 2) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i16 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i16 ! CHECK: %[[BITS:.*]] = arith.constant 16 : i16 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i16 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i16 ! CHECK: %[[SHIFT:.*]] = arith.shli %[[C__1]], %[[LEN]] : i16 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i16 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i16 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskl2_test ! CHECK-LABEL: maskl4_test @@ -56,11 +65,14 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskl(a, 4) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i32 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32 ! CHECK: %[[BITS:.*]] = arith.constant 32 : i32 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_VAL]] : i32 ! CHECK: %[[SHIFT:.*]] = arith.shli %[[C__1]], %[[LEN]] : i32 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_VAL]], %[[C__0]] : i32 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskl4_test ! CHECK-LABEL: maskl8_test @@ -71,12 +83,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskl(a, 8) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i64 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i64 ! CHECK: %[[BITS:.*]] = arith.constant 64 : i64 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i64 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i64 ! CHECK: %[[SHIFT:.*]] = arith.shli %[[C__1]], %[[LEN]] : i64 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i64 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i64 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskl8_test ! TODO: Code containing 128-bit integer literals current breaks. This is diff --git a/flang/test/Lower/Intrinsics/maskr.f90 b/flang/test/Lower/Intrinsics/maskr.f90 --- a/flang/test/Lower/Intrinsics/maskr.f90 +++ b/flang/test/Lower/Intrinsics/maskr.f90 @@ -9,11 +9,14 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskr(a) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i32 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32 ! CHECK: %[[BITS:.*]] = arith.constant 32 : i32 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_VAL]] : i32 ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[C__1]], %[[LEN]] : i32 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_VAL]], %[[C__0]] : i32 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskr_test ! CHECK-LABEL: maskr1_test @@ -24,12 +27,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskr(a, 1) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i8 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i8 ! CHECK: %[[BITS:.*]] = arith.constant 8 : i8 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i8 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i8 ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[C__1]], %[[LEN]] : i8 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i8 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i8 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskr1_test ! CHECK-LABEL: maskr2_test @@ -40,12 +46,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskr(a, 2) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i16 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i16 ! CHECK: %[[BITS:.*]] = arith.constant 16 : i16 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i16 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i16 ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[C__1]], %[[LEN]] : i16 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i16 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i16 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskr2_test ! CHECK-LABEL: maskr4_test @@ -56,11 +65,14 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskr(a, 4) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i32 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i32 ! CHECK: %[[BITS:.*]] = arith.constant 32 : i32 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_VAL]] : i32 ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[C__1]], %[[LEN]] : i32 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_VAL]], %[[C__0]] : i32 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskr4_test ! CHECK-LABEL: maskr8_test @@ -71,12 +83,15 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref b = maskr(a, 8) + ! CHECK: %[[C__0:.*]] = arith.constant 0 : i64 ! CHECK: %[[C__1:.*]] = arith.constant -1 : i64 ! CHECK: %[[BITS:.*]] = arith.constant 64 : i64 ! CHECK: %[[A_CONV:.*]] = fir.convert %[[A_VAL]] : (i32) -> i64 ! CHECK: %[[LEN:.*]] = arith.subi %[[BITS]], %[[A_CONV]] : i64 ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[C__1]], %[[LEN]] : i64 - ! CHECK: fir.store %[[SHIFT]] to %[[B]] : !fir.ref + ! CHECK: %[[IS0:.*]] = arith.cmpi eq, %[[A_CONV]], %[[C__0]] : i64 + ! CHECK: %[[RESULT:.*]] = arith.select %[[IS0]], %[[C__0]], %[[SHIFT]] : i64 + ! CHECK: fir.store %[[RESULT]] to %[[B]] : !fir.ref end subroutine maskr8_test ! TODO: Code containing 128-bit integer literals current breaks. This is