[flang-commits] [flang] [flang] preserve logical operations in single FIR operation (PR #190771)
via flang-commits
flang-commits at lists.llvm.org
Wed Apr 8 06:14:11 PDT 2026
https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/190771
>From 43844279e9803bab3fb6a167b9f23dc1d0c6ac4a Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 7 Apr 2026 02:59:17 -0700
Subject: [PATCH 1/2] [flang] preserve logical operations in single FIR
operation
---
.../include/flang/Optimizer/Dialect/FIROps.td | 71 +++++++++
.../flang/Optimizer/Dialect/FIRTypes.td | 3 +
flang/lib/Lower/ConvertExprToHLFIR.cpp | 28 +++-
.../lib/Lower/Support/ReductionProcessor.cpp | 39 ++---
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 145 ++++++++++++++++--
flang/lib/Optimizer/Dialect/FIROps.cpp | 76 +++++++++
.../Support/FIROpenACCTypeInterfaces.cpp | 31 +---
.../lib/Optimizer/Transforms/FIRToMemRef.cpp | 40 ++++-
flang/test/Fir/fir-ops.fir | 22 +++
flang/test/Fir/invalid.fir | 17 ++
flang/test/Fir/logical-convert.fir | 75 +++++++++
.../HLFIR/array-ctor-as-inlined-temp.f90 | 14 +-
flang/test/Lower/HLFIR/binary-ops.f90 | 10 +-
flang/test/Lower/HLFIR/expr-box.f90 | 5 +-
.../Lower/HLFIR/user-defined-assignment.f90 | 7 +-
flang/test/Lower/OpenACC/acc-reduction.f90 | 35 ++---
.../OpenMP/atomic-update-reassoc-logical.f90 | 45 ++----
.../wsloop-reduction-logical-and-byref.f90 | 42 ++---
.../OpenMP/wsloop-reduction-logical-and.f90 | 42 ++---
.../wsloop-reduction-logical-eqv-byref.f90 | 42 ++---
.../OpenMP/wsloop-reduction-logical-eqv.f90 | 42 ++---
.../wsloop-reduction-logical-neqv-byref.f90 | 42 ++---
.../OpenMP/wsloop-reduction-logical-neqv.f90 | 42 ++---
.../wsloop-reduction-logical-or-byref.f90 | 42 ++---
.../OpenMP/wsloop-reduction-logical-or.f90 | 42 ++---
flang/test/Lower/array-elemental-calls-2.f90 | 7 +-
.../test/Transforms/FIRToMemRef/logical.mlir | 28 ++++
27 files changed, 640 insertions(+), 394 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index f499be9fb5dd26..aa371511dc2d8b 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -2845,6 +2845,77 @@ def fir_DivcOp : ComplexArithmeticOp<"divc",
[DeclareOpInterfaceMethods<ArithFastMathInterface>]>;
// Pow is a builtin call and not a primitive
+// Logical operations
+
+class LogicalBinaryOp<string mnemonic, list<Trait> traits = []> :
+ fir_ArithmeticOp<mnemonic, traits>,
+ Arguments<(ins AnyLogicalOrIntegerLike:$lhs,
+ AnyLogicalOrIntegerLike:$rhs)>;
+
+def fir_LogicalAndOp : LogicalBinaryOp<"logical_and", [Commutative]> {
+ let summary = "logical AND";
+
+ let description = [{
+ Logical AND of two values of fir.logical or integer type.
+ Both operands and the result must have the same type.
+
+ ```
+ %r = fir.logical_and %a, %b : !fir.logical<4>
+ %s = fir.logical_and %x, %y : i32
+ ```
+ }];
+
+ let hasFolder = 1;
+}
+
+def fir_LogicalOrOp : LogicalBinaryOp<"logical_or", [Commutative]> {
+ let summary = "logical OR";
+
+ let description = [{
+ Logical OR of two values of fir.logical or integer type.
+ Both operands and the result must have the same type.
+
+ ```
+ %r = fir.logical_or %a, %b : !fir.logical<4>
+ %s = fir.logical_or %x, %y : i32
+ ```
+ }];
+
+ let hasFolder = 1;
+}
+
+def fir_EqvOp : LogicalBinaryOp<"eqv", [Commutative]> {
+ let summary = "logical equivalence";
+
+ let description = [{
+ Logical equivalence (EQV) of two values of fir.logical or integer type.
+ Both operands and the result must have the same type.
+
+ ```
+ %r = fir.eqv %a, %b : !fir.logical<4>
+ %s = fir.eqv %x, %y : i32
+ ```
+ }];
+
+ let hasFolder = 1;
+}
+
+def fir_NeqvOp : LogicalBinaryOp<"neqv", [Commutative]> {
+ let summary = "logical non-equivalence";
+
+ let description = [{
+ Logical non-equivalence (NEQV / XOR) of two values of fir.logical or
+ integer type. Both operands and the result must have the same type.
+
+ ```
+ %r = fir.neqv %a, %b : !fir.logical<4>
+ %s = fir.neqv %x, %y : i32
+ ```
+ }];
+
+ let hasFolder = 1;
+}
+
def fir_CmpcOp : fir_Op<"cmpc",
[NoMemoryEffect, SameTypeOperands, SameOperandsAndResultShape,
DeclareOpInterfaceMethods<ArithFastMathInterface>]> {
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 7c7fe706d29d45..c58d75851349ea 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -602,6 +602,9 @@ def AnyLogicalLike : TypeConstraint<Or<[BoolLike.predicate,
def AnyRealLike : TypeConstraint<FloatLike.predicate, "any real">;
def AnyIntegerType : Type<AnyIntegerLike.predicate, "any integer">;
def AnyLogicalType : Type<AnyLogicalLike.predicate, "any logical">;
+def AnyLogicalOrIntegerLike : TypeConstraint<Or<[
+ fir_LogicalType.predicate,
+ SignlessIntegerLike.predicate]>, "fir.logical or signless integer">;
def AnyFirComplexLike : TypeConstraint<CPred<"::fir::isa_complex($_self)">,
"any floating point complex type">;
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 0c015bc9a2f1b7..1251190ac183d4 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1326,6 +1326,33 @@ struct BinaryOp<Fortran::evaluate::LogicalOperation<KIND>> {
fir::FirOpBuilder &builder,
const Op &op, hlfir::Entity lhs,
hlfir::Entity rhs) {
+ bool lhsIsLogical = mlir::isa<fir::LogicalType>(lhs.getType());
+ bool rhsIsLogical = mlir::isa<fir::LogicalType>(rhs.getType());
+ if (lhsIsLogical || rhsIsLogical) {
+ // Use fir logical ops when at least one operand is a Fortran LOGICAL.
+ // Ensure both operands have the same type.
+ mlir::Type resTy = lhsIsLogical ? lhs.getType() : rhs.getType();
+ mlir::Value lhsVal = builder.createConvert(loc, resTy, lhs);
+ mlir::Value rhsVal = builder.createConvert(loc, resTy, rhs);
+ switch (op.logicalOperator) {
+ case Fortran::evaluate::LogicalOperator::And:
+ return hlfir::EntityWithAttributes{
+ fir::LogicalAndOp::create(builder, loc, resTy, lhsVal, rhsVal)};
+ case Fortran::evaluate::LogicalOperator::Or:
+ return hlfir::EntityWithAttributes{
+ fir::LogicalOrOp::create(builder, loc, resTy, lhsVal, rhsVal)};
+ case Fortran::evaluate::LogicalOperator::Eqv:
+ return hlfir::EntityWithAttributes{
+ fir::EqvOp::create(builder, loc, resTy, lhsVal, rhsVal)};
+ case Fortran::evaluate::LogicalOperator::Neqv:
+ return hlfir::EntityWithAttributes{
+ fir::NeqvOp::create(builder, loc, resTy, lhsVal, rhsVal)};
+ case Fortran::evaluate::LogicalOperator::Not:
+ llvm_unreachable(".NOT. is not a binary operator");
+ }
+ llvm_unreachable("unhandled logical operation");
+ }
+ // Both operands are i1 (from arithmetic comparisons): use arith ops.
mlir::Type i1Type = builder.getI1Type();
mlir::Value i1Lhs = builder.createConvert(loc, i1Type, lhs);
mlir::Value i1Rhs = builder.createConvert(loc, i1Type, rhs);
@@ -1343,7 +1370,6 @@ struct BinaryOp<Fortran::evaluate::LogicalOperation<KIND>> {
return hlfir::EntityWithAttributes{mlir::arith::CmpIOp::create(
builder, loc, mlir::arith::CmpIPredicate::ne, i1Lhs, i1Rhs)};
case Fortran::evaluate::LogicalOperator::Not:
- // lib/evaluate expression for .NOT. is Fortran::evaluate::Not<KIND>.
llvm_unreachable(".NOT. is not a binary operator");
}
llvm_unreachable("unhandled logical operation");
diff --git a/flang/lib/Lower/Support/ReductionProcessor.cpp b/flang/lib/Lower/Support/ReductionProcessor.cpp
index e0cba4c512258d..04efba463de492 100644
--- a/flang/lib/Lower/Support/ReductionProcessor.cpp
+++ b/flang/lib/Lower/Support/ReductionProcessor.cpp
@@ -322,42 +322,27 @@ mlir::Value ReductionProcessor::createScalarCombiner(
fir::MulcOp>(builder, type, loc, op1, op2);
break;
case ReductionIdentifier::AND: {
- mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1);
- mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2);
-
- mlir::Value andiOp =
- mlir::arith::AndIOp::create(builder, loc, op1I1, op2I1);
-
- reductionOp = builder.createConvert(loc, type, andiOp);
+ mlir::Value v1 = builder.createConvert(loc, type, op1);
+ mlir::Value v2 = builder.createConvert(loc, type, op2);
+ reductionOp = fir::LogicalAndOp::create(builder, loc, type, v1, v2);
break;
}
case ReductionIdentifier::OR: {
- mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1);
- mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2);
-
- mlir::Value oriOp = mlir::arith::OrIOp::create(builder, loc, op1I1, op2I1);
-
- reductionOp = builder.createConvert(loc, type, oriOp);
+ mlir::Value v1 = builder.createConvert(loc, type, op1);
+ mlir::Value v2 = builder.createConvert(loc, type, op2);
+ reductionOp = fir::LogicalOrOp::create(builder, loc, type, v1, v2);
break;
}
case ReductionIdentifier::EQV: {
- mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1);
- mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2);
-
- mlir::Value cmpiOp = mlir::arith::CmpIOp::create(
- builder, loc, mlir::arith::CmpIPredicate::eq, op1I1, op2I1);
-
- reductionOp = builder.createConvert(loc, type, cmpiOp);
+ mlir::Value v1 = builder.createConvert(loc, type, op1);
+ mlir::Value v2 = builder.createConvert(loc, type, op2);
+ reductionOp = fir::EqvOp::create(builder, loc, type, v1, v2);
break;
}
case ReductionIdentifier::NEQV: {
- mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1);
- mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2);
-
- mlir::Value cmpiOp = mlir::arith::CmpIOp::create(
- builder, loc, mlir::arith::CmpIPredicate::ne, op1I1, op2I1);
-
- reductionOp = builder.createConvert(loc, type, cmpiOp);
+ mlir::Value v1 = builder.createConvert(loc, type, op1);
+ mlir::Value v2 = builder.createConvert(loc, type, op2);
+ reductionOp = fir::NeqvOp::create(builder, loc, type, v1, v2);
break;
}
default:
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 2d01463cf604d8..c2cc82203c4955 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -65,6 +65,7 @@
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/CommandLine.h"
namespace fir {
#define GEN_PASS_DEF_FIRTOLLVMLOWERING
@@ -73,6 +74,14 @@ namespace fir {
#define DEBUG_TYPE "flang-codegen"
+static llvm::cl::opt<bool> useNativeLogicalOps(
+ "fir-logical-native-ops",
+ llvm::cl::desc(
+ "Use bitwise operations on the storage type for logical operations "
+ "instead of normalizing to i1. Requires that all logical values "
+ "are in their canonical representation."),
+ llvm::cl::init(false));
+
// TODO: This should really be recovered from the specified target.
static constexpr unsigned defaultAlign = 8;
@@ -4292,6 +4301,115 @@ struct NegcOpConversion : public fir::FIROpConversion<fir::NegcOp> {
}
};
+/// Normalize a logical value to i1 by comparing with zero.
+static mlir::Value
+normalizeLogicalToI1(mlir::ConversionPatternRewriter &rewriter,
+ mlir::Location loc, mlir::Value value) {
+ mlir::Type ty = value.getType();
+ auto i1Ty = mlir::IntegerType::get(rewriter.getContext(), 1);
+ if (ty == i1Ty)
+ return value;
+ mlir::Value zero = fir::genConstantIndex(loc, ty, rewriter, 0);
+ return mlir::LLVM::ICmpOp::create(rewriter, loc,
+ mlir::LLVM::ICmpPredicate::ne, value, zero);
+}
+
+/// Extend an i1 value to the given integer type. Returns the value unchanged
+/// if it is already the target type.
+static mlir::Value extendI1ToType(mlir::ConversionPatternRewriter &rewriter,
+ mlir::Location loc, mlir::Value i1Val,
+ mlir::Type toTy) {
+ auto i1Ty = mlir::IntegerType::get(rewriter.getContext(), 1);
+ if (toTy == i1Ty)
+ return i1Val;
+ return mlir::LLVM::ZExtOp::create(rewriter, loc, toTy, i1Val);
+}
+
+/// Logical AND codegen.
+struct LogicalAndOpConversion : public fir::FIROpConversion<fir::LogicalAndOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::LogicalAndOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Type resTy = convertType(op.getType());
+ auto loc = op.getLoc();
+ if (useNativeLogicalOps) {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(
+ op, resTy, adaptor.getLhs(), adaptor.getRhs());
+ } else {
+ auto lhs = normalizeLogicalToI1(rewriter, loc, adaptor.getLhs());
+ auto rhs = normalizeLogicalToI1(rewriter, loc, adaptor.getRhs());
+ auto res = mlir::LLVM::AndOp::create(rewriter, loc, lhs, rhs);
+ rewriter.replaceOp(op, extendI1ToType(rewriter, loc, res, resTy));
+ }
+ return mlir::success();
+ }
+};
+
+/// Logical OR codegen.
+struct LogicalOrOpConversion : public fir::FIROpConversion<fir::LogicalOrOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::LogicalOrOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Type resTy = convertType(op.getType());
+ auto loc = op.getLoc();
+ if (useNativeLogicalOps) {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, resTy, adaptor.getLhs(),
+ adaptor.getRhs());
+ } else {
+ auto lhs = normalizeLogicalToI1(rewriter, loc, adaptor.getLhs());
+ auto rhs = normalizeLogicalToI1(rewriter, loc, adaptor.getRhs());
+ auto res = mlir::LLVM::OrOp::create(rewriter, loc, lhs, rhs);
+ rewriter.replaceOp(op, extendI1ToType(rewriter, loc, res, resTy));
+ }
+ return mlir::success();
+ }
+};
+
+/// Logical equivalence codegen.
+struct EqvOpConversion : public fir::FIROpConversion<fir::EqvOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::EqvOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Type resTy = convertType(op.getType());
+ auto loc = op.getLoc();
+ auto lhs = normalizeLogicalToI1(rewriter, loc, adaptor.getLhs());
+ auto rhs = normalizeLogicalToI1(rewriter, loc, adaptor.getRhs());
+ auto res = mlir::LLVM::ICmpOp::create(
+ rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhs, rhs);
+ rewriter.replaceOp(op, extendI1ToType(rewriter, loc, res, resTy));
+ return mlir::success();
+ }
+};
+
+/// Logical non-equivalence codegen.
+struct NeqvOpConversion : public fir::FIROpConversion<fir::NeqvOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::NeqvOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Type resTy = convertType(op.getType());
+ auto loc = op.getLoc();
+ if (useNativeLogicalOps) {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(
+ op, resTy, adaptor.getLhs(), adaptor.getRhs());
+ } else {
+ auto lhs = normalizeLogicalToI1(rewriter, loc, adaptor.getLhs());
+ auto rhs = normalizeLogicalToI1(rewriter, loc, adaptor.getRhs());
+ auto res = mlir::LLVM::ICmpOp::create(
+ rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhs, rhs);
+ rewriter.replaceOp(op, extendI1ToType(rewriter, loc, res, resTy));
+ }
+ return mlir::success();
+ }
+};
+
struct BoxOffsetOpConversion : public fir::FIROpConversion<fir::BoxOffsetOp> {
using FIROpConversion::FIROpConversion;
@@ -4641,19 +4759,20 @@ void fir::populateFIRToLLVMConversionPatterns(
DoConcurrentSpecifierOpConversion<fir::LocalitySpecifierOp>,
DoConcurrentSpecifierOpConversion<fir::DeclareReductionOp>,
DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion,
- EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion,
- FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion,
- GlobalOpConversion, InsertOnRangeOpConversion, IsPresentOpConversion,
- LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion,
- NegcOpConversion, NoReassocOpConversion, PrefetchOpConversion,
- SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion,
- SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion,
- ShiftOpConversion, SliceOpConversion, StoreOpConversion,
- StringLitOpConversion, SubcOpConversion, TypeDescOpConversion,
- TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion,
- UndefOpConversion, UnreachableOpConversion, UseStmtOpConversion,
- XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion,
- ZeroOpConversion>(converter, options);
+ EmboxProcOpConversion, EqvOpConversion, ExtractValueOpConversion,
+ FieldIndexOpConversion, FirEndOpConversion, FreeMemOpConversion,
+ GlobalLenOpConversion, GlobalOpConversion, InsertOnRangeOpConversion,
+ IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion,
+ LogicalAndOpConversion, LogicalOrOpConversion, MulcOpConversion,
+ NegcOpConversion, NeqvOpConversion, NoReassocOpConversion,
+ PrefetchOpConversion, SelectCaseOpConversion, SelectOpConversion,
+ SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion,
+ ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion,
+ StoreOpConversion, StringLitOpConversion, SubcOpConversion,
+ TypeDescOpConversion, TypeInfoOpConversion, UnboxCharOpConversion,
+ UnboxProcOpConversion, UndefOpConversion, UnreachableOpConversion,
+ UseStmtOpConversion, XArrayCoorOpConversion, XEmboxOpConversion,
+ XReboxOpConversion, ZeroOpConversion>(converter, options);
// Patterns that are populated without a type converter do not trigger
// target materializations for the operands of the root op.
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 93a141da111a23..cf0ceed7fbb396 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1639,6 +1639,82 @@ mlir::OpFoldResult fir::ConvertOp::fold(FoldAdaptor adaptor) {
return {};
}
+//===----------------------------------------------------------------------===//
+// Logical binary operations fold helpers
+//===----------------------------------------------------------------------===//
+
+/// If \p value is a fir.convert of an arith.constant i1, return the i1 value.
+static std::optional<bool> getLogicalConstant(mlir::Value value) {
+ auto convertOp = value.getDefiningOp<fir::ConvertOp>();
+ if (!convertOp)
+ return std::nullopt;
+ if (auto cst = fir::getIntIfConstant(convertOp.getValue()))
+ return *cst != 0;
+ return std::nullopt;
+}
+
+/// Build a logical constant: fir.convert(arith.constant) if the result type
+/// is fir.logical, or arith.constant if it is an integer type.
+static mlir::OpFoldResult logicalConstantFoldResult(mlir::Type resTy,
+ bool value) {
+ if (mlir::isa<fir::LogicalType>(resTy))
+ return {};
+ auto intTy = mlir::cast<mlir::IntegerType>(resTy);
+ return mlir::IntegerAttr::get(intTy, value ? 1 : 0);
+}
+
+mlir::OpFoldResult fir::LogicalAndOp::fold(FoldAdaptor adaptor) {
+ auto lhsCst = getLogicalConstant(getLhs());
+ auto rhsCst = getLogicalConstant(getRhs());
+ if (lhsCst && rhsCst)
+ return logicalConstantFoldResult(getType(), *lhsCst && *rhsCst);
+ // land(x, true) -> x
+ if (rhsCst && *rhsCst)
+ return getLhs();
+ if (lhsCst && *lhsCst)
+ return getRhs();
+ return {};
+}
+
+mlir::OpFoldResult fir::LogicalOrOp::fold(FoldAdaptor adaptor) {
+ auto lhsCst = getLogicalConstant(getLhs());
+ auto rhsCst = getLogicalConstant(getRhs());
+ if (lhsCst && rhsCst)
+ return logicalConstantFoldResult(getType(), *lhsCst || *rhsCst);
+ // lor(x, false) -> x
+ if (rhsCst && !*rhsCst)
+ return getLhs();
+ if (lhsCst && !*lhsCst)
+ return getRhs();
+ return {};
+}
+
+mlir::OpFoldResult fir::EqvOp::fold(FoldAdaptor adaptor) {
+ auto lhsCst = getLogicalConstant(getLhs());
+ auto rhsCst = getLogicalConstant(getRhs());
+ if (lhsCst && rhsCst)
+ return logicalConstantFoldResult(getType(), *lhsCst == *rhsCst);
+ // eqv(x, true) -> x
+ if (rhsCst && *rhsCst)
+ return getLhs();
+ if (lhsCst && *lhsCst)
+ return getRhs();
+ return {};
+}
+
+mlir::OpFoldResult fir::NeqvOp::fold(FoldAdaptor adaptor) {
+ auto lhsCst = getLogicalConstant(getLhs());
+ auto rhsCst = getLogicalConstant(getRhs());
+ if (lhsCst && rhsCst)
+ return logicalConstantFoldResult(getType(), *lhsCst != *rhsCst);
+ // neqv(x, false) -> x
+ if (rhsCst && !*rhsCst)
+ return getLhs();
+ if (lhsCst && !*lhsCst)
+ return getRhs();
+ return {};
+}
+
bool fir::ConvertOp::isInteger(mlir::Type ty) {
return mlir::isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType>(ty);
}
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
index 25af35513d18d0..28d46774b3d10c 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
@@ -1012,23 +1012,9 @@ template <typename Op>
static mlir::Value genLogicalCombiner(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value value1,
mlir::Value value2) {
- mlir::Type i1 = builder.getI1Type();
- mlir::Value v1 = fir::ConvertOp::create(builder, loc, i1, value1);
- mlir::Value v2 = fir::ConvertOp::create(builder, loc, i1, value2);
- mlir::Value combined = Op::create(builder, loc, v1, v2);
- return fir::ConvertOp::create(builder, loc, value1.getType(), combined);
-}
-
-static mlir::Value genComparisonCombiner(fir::FirOpBuilder &builder,
- mlir::Location loc,
- mlir::arith::CmpIPredicate pred,
- mlir::Value value1,
- mlir::Value value2) {
- mlir::Type i1 = builder.getI1Type();
- mlir::Value v1 = fir::ConvertOp::create(builder, loc, i1, value1);
- mlir::Value v2 = fir::ConvertOp::create(builder, loc, i1, value2);
- mlir::Value add = mlir::arith::CmpIOp::create(builder, loc, pred, v1, v2);
- return fir::ConvertOp::create(builder, loc, value1.getType(), add);
+ mlir::Type type = value1.getType();
+ mlir::Value v2 = builder.createConvert(loc, type, value2);
+ return Op::create(builder, loc, type, value1, v2);
}
static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder,
@@ -1098,19 +1084,16 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder,
return mlir::arith::XOrIOp::create(builder, loc, value1, value2);
if (op == mlir::acc::ReductionOperator::AccLand)
- return genLogicalCombiner<mlir::arith::AndIOp>(builder, loc, value1,
- value2);
+ return genLogicalCombiner<fir::LogicalAndOp>(builder, loc, value1, value2);
if (op == mlir::acc::ReductionOperator::AccLor)
- return genLogicalCombiner<mlir::arith::OrIOp>(builder, loc, value1, value2);
+ return genLogicalCombiner<fir::LogicalOrOp>(builder, loc, value1, value2);
if (op == mlir::acc::ReductionOperator::AccEqv)
- return genComparisonCombiner(builder, loc, mlir::arith::CmpIPredicate::eq,
- value1, value2);
+ return genLogicalCombiner<fir::EqvOp>(builder, loc, value1, value2);
if (op == mlir::acc::ReductionOperator::AccNeqv)
- return genComparisonCombiner(builder, loc, mlir::arith::CmpIPredicate::ne,
- value1, value2);
+ return genLogicalCombiner<fir::NeqvOp>(builder, loc, value1, value2);
TODO(loc, "reduction operator");
}
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index 4f8c8582fb0e2f..a0b1ff66a62fe9 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -69,6 +69,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -1081,6 +1082,29 @@ void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
replaceFIRMemrefs(firMemref, converted, rewriter);
}
+// Lower operand and result type of FIR logical operation to get rid
+// of bitcast after loads from memref and before store to memref
+// storing arrays of logicals as integers.
+template <typename Op>
+static void rewriteLogicalOperation(Op op, PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ mlir::Type oldType = op.getResult().getType();
+ mlir::Type convertedTy = typeConverter.convertType(oldType);
+ if (convertedTy == oldType)
+ return;
+ rewriter.setInsertionPoint(op);
+ mlir::Location loc = op.getLoc();
+ // Inserted bitcast from/to logical will be folded with the one created
+ // around load/store.
+ mlir::Value lhs =
+ createTypeConversion(rewriter, loc, convertedTy, op.getLhs());
+ mlir::Value rhs =
+ createTypeConversion(rewriter, loc, convertedTy, op.getRhs());
+ auto newOp = Op::create(rewriter, loc, convertedTy, lhs, rhs);
+ mlir::Value result = createTypeConversion(rewriter, loc, oldType, newOp);
+ rewriter.replaceOp(op, result);
+}
+
void FIRToMemRef::runOnOperation() {
LLVM_DEBUG(llvm::dbgs() << "Enter FIRToMemRef()\n");
@@ -1099,10 +1123,18 @@ void FIRToMemRef::runOnOperation() {
});
op.walk([&](Operation *op) {
- if (fir::LoadOp loadOp = dyn_cast<fir::LoadOp>(op))
- rewriteLoadOp(loadOp, rewriter, typeConverter);
- else if (fir::StoreOp storeOp = dyn_cast<fir::StoreOp>(op))
- rewriteStoreOp(storeOp, rewriter, typeConverter);
+ llvm::TypeSwitch<Operation *>(op)
+ .Case<fir::LoadOp>([&](auto loadOp) {
+ rewriteLoadOp(loadOp, rewriter, typeConverter);
+ })
+ .Case<fir::StoreOp>([&](auto storeOp) {
+ rewriteStoreOp(storeOp, rewriter, typeConverter);
+ })
+ .Case<fir::LogicalAndOp, fir::LogicalOrOp, fir::EqvOp, fir::NeqvOp>(
+ [&](auto logicalOp) {
+ rewriteLogicalOperation(logicalOp, rewriter, typeConverter);
+ })
+ .Default([](Operation *) {});
});
for (auto eraseOp : eraseOps)
diff --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir
index c9ba08a5a47c8e..2dd220134a73db 100644
--- a/flang/test/Fir/fir-ops.fir
+++ b/flang/test/Fir/fir-ops.fir
@@ -1084,3 +1084,25 @@ func.func @test_bitcast(%arg0: i32, %arg1: f32, %arg2: !fir.logical<4>, %arg3: !
%8 = fir.bitcast %arg0 : (i32) -> !fir.logical<4>
return
}
+
+// CHECK-LABEL: func @test_logical_ops(
+// CHECK-SAME: %[[L1:.*]]: !fir.logical<4>, %[[L2:.*]]: !fir.logical<4>, %[[I1:.*]]: i32, %[[I2:.*]]: i32)
+func.func @test_logical_ops(%l1: !fir.logical<4>, %l2: !fir.logical<4>, %i1: i32, %i2: i32) {
+// CHECK: %{{.*}} = fir.logical_and %[[L1]], %[[L2]] : !fir.logical<4>
+ %0 = fir.logical_and %l1, %l2 : !fir.logical<4>
+// CHECK: %{{.*}} = fir.logical_or %[[L1]], %[[L2]] : !fir.logical<4>
+ %1 = fir.logical_or %l1, %l2 : !fir.logical<4>
+// CHECK: %{{.*}} = fir.eqv %[[L1]], %[[L2]] : !fir.logical<4>
+ %2 = fir.eqv %l1, %l2 : !fir.logical<4>
+// CHECK: %{{.*}} = fir.neqv %[[L1]], %[[L2]] : !fir.logical<4>
+ %3 = fir.neqv %l1, %l2 : !fir.logical<4>
+// CHECK: %{{.*}} = fir.logical_and %[[I1]], %[[I2]] : i32
+ %4 = fir.logical_and %i1, %i2 : i32
+// CHECK: %{{.*}} = fir.logical_or %[[I1]], %[[I2]] : i32
+ %5 = fir.logical_or %i1, %i2 : i32
+// CHECK: %{{.*}} = fir.eqv %[[I1]], %[[I2]] : i32
+ %6 = fir.eqv %i1, %i2 : i32
+// CHECK: %{{.*}} = fir.neqv %[[I1]], %[[I2]] : i32
+ %7 = fir.neqv %i1, %i2 : i32
+ return
+}
diff --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir
index 9ab5e4f8553d1c..5471bcd8acc292 100644
--- a/flang/test/Fir/invalid.fir
+++ b/flang/test/Fir/invalid.fir
@@ -1539,3 +1539,20 @@ func.func @bitcast_size_mismatch(%arg0: i32) -> f64 {
%0 = fir.bitcast %arg0 : (i32) -> f64
return %0 : f64
}
+
+// -----
+
+func.func @logical_and_type_mismatch(%a: !fir.logical<4>, %b: !fir.logical<2>) {
+ // expected-note at -1 {{prior use here}}
+ // expected-error at +1 {{use of value '%b' expects different type than prior uses: '!fir.logical<4>' vs '!fir.logical<2>'}}
+ %0 = fir.logical_and %a, %b : !fir.logical<4>
+ return
+}
+
+// -----
+
+func.func @logical_or_float(%a: f32, %b: f32) {
+ // expected-error at +1 {{'fir.logical_or' op operand #0 must be fir.logical or signless integer, but got 'f32'}}
+ %0 = fir.logical_or %a, %b : f32
+ return
+}
diff --git a/flang/test/Fir/logical-convert.fir b/flang/test/Fir/logical-convert.fir
index 4cc081934db430..cf07480e641a97 100644
--- a/flang/test/Fir/logical-convert.fir
+++ b/flang/test/Fir/logical-convert.fir
@@ -511,3 +511,78 @@ func.func @test_l8_l4(%arg0: !fir.logical<8>) -> !fir.logical<4> {
%0 = fir.convert %arg0 : (!fir.logical<8>) -> !fir.logical<4>
return %0 : !fir.logical<4>
}
+// -----
+// CHECK-LABEL: @test_logical_and_l4
+// CHECK: [[ZERO0:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[A:%[0-9]*]] = llvm.icmp "ne" %arg0, [[ZERO0]] : i32
+// CHECK: [[ZERO1:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[B:%[0-9]*]] = llvm.icmp "ne" %arg1, [[ZERO1]] : i32
+// CHECK: [[RES:%[0-9]*]] = llvm.and [[A]], [[B]] : i1
+// CHECK: [[EXT:%[0-9]*]] = llvm.zext [[RES]] : i1 to i32
+// CHECK: llvm.return [[EXT]] : i32
+func.func @test_logical_and_l4(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.logical_and %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+// -----
+// CHECK-LABEL: @test_logical_or_l4
+// CHECK: [[ZERO0:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[A:%[0-9]*]] = llvm.icmp "ne" %arg0, [[ZERO0]] : i32
+// CHECK: [[ZERO1:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[B:%[0-9]*]] = llvm.icmp "ne" %arg1, [[ZERO1]] : i32
+// CHECK: [[RES:%[0-9]*]] = llvm.or [[A]], [[B]] : i1
+// CHECK: [[EXT:%[0-9]*]] = llvm.zext [[RES]] : i1 to i32
+// CHECK: llvm.return [[EXT]] : i32
+func.func @test_logical_or_l4(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.logical_or %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+// -----
+// CHECK-LABEL: @test_eqv_l4
+// CHECK: [[ZERO0:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[A:%[0-9]*]] = llvm.icmp "ne" %arg0, [[ZERO0]] : i32
+// CHECK: [[ZERO1:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[B:%[0-9]*]] = llvm.icmp "ne" %arg1, [[ZERO1]] : i32
+// CHECK: [[RES:%[0-9]*]] = llvm.icmp "eq" [[A]], [[B]] : i1
+// CHECK: [[EXT:%[0-9]*]] = llvm.zext [[RES]] : i1 to i32
+// CHECK: llvm.return [[EXT]] : i32
+func.func @test_eqv_l4(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.eqv %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+// -----
+// CHECK-LABEL: @test_neqv_l4
+// CHECK: [[ZERO0:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[A:%[0-9]*]] = llvm.icmp "ne" %arg0, [[ZERO0]] : i32
+// CHECK: [[ZERO1:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[B:%[0-9]*]] = llvm.icmp "ne" %arg1, [[ZERO1]] : i32
+// CHECK: [[RES:%[0-9]*]] = llvm.icmp "ne" [[A]], [[B]] : i1
+// CHECK: [[EXT:%[0-9]*]] = llvm.zext [[RES]] : i1 to i32
+// CHECK: llvm.return [[EXT]] : i32
+func.func @test_neqv_l4(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.neqv %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+// -----
+// Test on i1 type (from comparisons)
+// CHECK-LABEL: @test_logical_and_i1
+// CHECK: [[RES:%[0-9]*]] = llvm.and %arg0, %arg1 : i1
+// CHECK: llvm.return [[RES]] : i1
+func.func @test_logical_and_i1(%arg0: i1, %arg1: i1) -> i1 {
+ %0 = fir.logical_and %arg0, %arg1 : i1
+ return %0 : i1
+}
+// -----
+// Test on i32 type
+// CHECK-LABEL: @test_logical_and_i32
+// CHECK: [[ZERO0:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[A:%[0-9]*]] = llvm.icmp "ne" %arg0, [[ZERO0]] : i32
+// CHECK: [[ZERO1:%[0-9]*]] = llvm.mlir.constant(0 : i64) : i32
+// CHECK: [[B:%[0-9]*]] = llvm.icmp "ne" %arg1, [[ZERO1]] : i32
+// CHECK: [[RES:%[0-9]*]] = llvm.and [[A]], [[B]] : i1
+// CHECK: [[EXT:%[0-9]*]] = llvm.zext [[RES]] : i1 to i32
+// CHECK: llvm.return [[EXT]] : i32
+func.func @test_logical_and_i32(%arg0: i32, %arg1: i32) -> i32 {
+ %0 = fir.logical_and %arg0, %arg1 : i32
+ return %0 : i32
+}
diff --git a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
index 6fcd942f4a1e5f..6f300b8dfaa43e 100644
--- a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
@@ -97,15 +97,13 @@ subroutine test_simple_logical(a, b)
! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_11]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_13]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_16:.*]] = arith.andi %[[VAL_14]], %[[VAL_15]] : i1
-! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_10]]) : (!fir.heap<!fir.array<2x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
-! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_17]] : i1, !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_18:.*]] = arith.constant true
-! CHECK: %[[VAL_19:.*]] = hlfir.as_expr %[[VAL_8]]#0 move %[[VAL_18]] : (!fir.heap<!fir.array<2x!fir.logical<4>>>, i1) -> !hlfir.expr<2x!fir.logical<4>>
+! CHECK: %[[VAL_14:.*]] = fir.logical_and %[[VAL_12]], %[[VAL_13]] : !fir.logical<4>
+! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_10]]) : (!fir.heap<!fir.array<2x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
+! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_15]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_16:.*]] = arith.constant true
+! CHECK: %[[VAL_17:.*]] = hlfir.as_expr %[[VAL_8]]#0 move %[[VAL_16]] : (!fir.heap<!fir.array<2x!fir.logical<4>>>, i1) -> !hlfir.expr<2x!fir.logical<4>>
! CHECK: fir.call
-! CHECK: hlfir.destroy %[[VAL_19]] : !hlfir.expr<2x!fir.logical<4>>
+! CHECK: hlfir.destroy %[[VAL_17]] : !hlfir.expr<2x!fir.logical<4>>
subroutine test_implied_do(n)
integer(8) :: n
diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index 3a83cd44d3c2ea..dffd67a247075e 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -294,30 +294,28 @@ subroutine logical_and(x, y, z)
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_6]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_7]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_10:.*]] = arith.andi %[[VAL_8]], %[[VAL_9]] : i1
+! CHECK: %[[VAL_8:.*]] = fir.logical_and %[[VAL_6]], %[[VAL_7]] : !fir.logical<4>
subroutine logical_or(x, y, z)
logical :: x, y, z
x = y.or.z
end subroutine
! CHECK-LABEL: func.func @_QPlogical_or(
-! CHECK: %[[VAL_10:.*]] = arith.ori
+! CHECK: %[[VAL_8:.*]] = fir.logical_or {{.*}} : !fir.logical<4>
subroutine logical_eqv(x, y, z)
logical :: x, y, z
x = y.eqv.z
end subroutine
! CHECK-LABEL: func.func @_QPlogical_eqv(
-! CHECK: %[[VAL_10:.*]] = arith.cmpi eq
+! CHECK: %[[VAL_8:.*]] = fir.eqv {{.*}} : !fir.logical<4>
subroutine logical_neqv(x, y, z)
logical :: x, y, z
x = y.neqv.z
end subroutine
! CHECK-LABEL: func.func @_QPlogical_neqv(
-! CHECK: %[[VAL_10:.*]] = arith.cmpi ne
+! CHECK: %[[VAL_8:.*]] = fir.neqv {{.*}} : !fir.logical<4>
subroutine cmplx_ctor(z, x, y)
complex :: z
diff --git a/flang/test/Lower/HLFIR/expr-box.f90 b/flang/test/Lower/HLFIR/expr-box.f90
index 4631d18e481bdc..2cc46666b71fbe 100644
--- a/flang/test/Lower/HLFIR/expr-box.f90
+++ b/flang/test/Lower/HLFIR/expr-box.f90
@@ -19,9 +19,8 @@ subroutine test_place_in_memory_and_embox()
end subroutine
! CHECK-LABEL: func.func @_QPtest_place_in_memory_and_embox(
! CHECK: %[[TEMP:.*]] = fir.alloca !fir.logical<8>
-! CHECK: %[[AND:.*]] = arith.andi {{.*}}
-! CHECK: %[[CAST:.*]] = fir.convert %[[AND]] : (i1) -> !fir.logical<8>
-! CHECK: fir.store %[[CAST]] to %[[TEMP]] : !fir.ref<!fir.logical<8>>
+! CHECK: %[[AND:.*]] = fir.logical_and {{.*}}
+! CHECK: fir.store %[[AND]] to %[[TEMP]] : !fir.ref<!fir.logical<8>>
! CHECK: %[[BOX:.*]] = fir.embox %[[TEMP]] : (!fir.ref<!fir.logical<8>>) -> !fir.box<!fir.logical<8>>
! CHECK: %[[BOX_CAST:.*]] = fir.convert %[[BOX]] : (!fir.box<!fir.logical<8>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[BOX_CAST]])
diff --git a/flang/test/Lower/HLFIR/user-defined-assignment.f90 b/flang/test/Lower/HLFIR/user-defined-assignment.f90
index 2dffd92ca50f58..13e1f2fde9558b 100644
--- a/flang/test/Lower/HLFIR/user-defined-assignment.f90
+++ b/flang/test/Lower/HLFIR/user-defined-assignment.f90
@@ -142,11 +142,8 @@ subroutine test_where_user_def_assignment(i, l, l2)
! CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_10]]) : (!fir.box<!fir.array<?x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_11]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_13]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_17:.*]] = arith.cmpi ne, %[[VAL_15]], %[[VAL_16]] : i1
-! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.yield_element %[[VAL_18]] : !fir.logical<4>
+! CHECK: %[[VAL_15:.*]] = fir.neqv %[[VAL_13]], %[[VAL_14]] : !fir.logical<4>
+! CHECK: hlfir.yield_element %[[VAL_15]] : !fir.logical<4>
! CHECK: }
! CHECK: hlfir.yield %[[VAL_19:.*]] : !hlfir.expr<?x!fir.logical<4>> cleanup {
! CHECK: hlfir.destroy %[[VAL_19]] : !hlfir.expr<?x!fir.logical<4>>
diff --git a/flang/test/Lower/OpenACC/acc-reduction.f90 b/flang/test/Lower/OpenACC/acc-reduction.f90
index 49789efc545ba2..a1f20d777cee25 100644
--- a/flang/test/Lower/OpenACC/acc-reduction.f90
+++ b/flang/test/Lower/OpenACC/acc-reduction.f90
@@ -23,11 +23,8 @@
! CHECK: %[[BOX_ADDR_1:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<!fir.logical<4>>>) -> !fir.heap<!fir.logical<4>>
! CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.heap<!fir.logical<4>>
! CHECK: %[[LOAD_3:.*]] = fir.load %[[BOX_ADDR_1]] : !fir.heap<!fir.logical<4>>
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_3]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_2]] : (!fir.logical<4>) -> i1
-! CHECK: %[[ORI_0:.*]] = arith.ori %[[CONVERT_0]], %[[CONVERT_1]] : i1
-! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[ORI_0]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[CONVERT_2]] to %[[BOX_ADDR_1]] : !fir.logical<4>, !fir.heap<!fir.logical<4>>
+! CHECK: %[[ORI_0:.*]] = fir.logical_or %[[LOAD_3]], %[[LOAD_2]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[ORI_0]] to %[[BOX_ADDR_1]] : !fir.logical<4>, !fir.heap<!fir.logical<4>>
! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.logical<4>>>>
! CHECK-LABEL: } destroy {
@@ -710,11 +707,8 @@
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CMPI_0:.*]] = arith.cmpi ne, %[[CONVERT_0]], %[[CONVERT_1]] : i1
-! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[CMPI_0]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[CMPI_0:.*]] = fir.neqv %[[LOAD_1]], %[[LOAD_0]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[CMPI_0]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>>
! CHECK: }
@@ -729,11 +723,8 @@
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CMPI_0:.*]] = arith.cmpi eq, %[[CONVERT_0]], %[[CONVERT_1]] : i1
-! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[CMPI_0]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[CMPI_0:.*]] = fir.eqv %[[LOAD_1]], %[[LOAD_0]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[CMPI_0]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>>
! CHECK: }
@@ -748,11 +739,8 @@
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[ORI_0:.*]] = arith.ori %[[CONVERT_0]], %[[CONVERT_1]] : i1
-! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[ORI_0]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[ORI_0:.*]] = fir.logical_or %[[LOAD_1]], %[[LOAD_0]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[ORI_0]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>>
! CHECK: }
@@ -767,11 +755,8 @@
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[ANDI_0:.*]] = arith.andi %[[CONVERT_0]], %[[CONVERT_1]] : i1
-! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[ANDI_0]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[ANDI_0:.*]] = fir.logical_and %[[LOAD_1]], %[[LOAD_0]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[ANDI_0]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>>
! CHECK: }
diff --git a/flang/test/Lower/OpenMP/atomic-update-reassoc-logical.f90 b/flang/test/Lower/OpenMP/atomic-update-reassoc-logical.f90
index ccde4fed12f2f9..564f0f9bd5fa3c 100644
--- a/flang/test/Lower/OpenMP/atomic-update-reassoc-logical.f90
+++ b/flang/test/Lower/OpenMP/atomic-update-reassoc-logical.f90
@@ -14,14 +14,10 @@ subroutine f00(x, y, z)
!CHECK: %[[Z:[0-9]+]]:2 = hlfir.declare %arg2
!CHECK: %[[LOAD_Y:[0-9]+]] = fir.load %[[Y]]#0 : !fir.ref<!fir.logical<4>>
!CHECK: %[[LOAD_Z:[0-9]+]] = fir.load %[[Z]]#0 : !fir.ref<!fir.logical<4>>
-!CHECK: %[[CVT_Y:[0-9]+]] = fir.convert %[[LOAD_Y]] : (!fir.logical<4>) -> i1
-!CHECK: %[[CVT_Z:[0-9]+]] = fir.convert %[[LOAD_Z]] : (!fir.logical<4>) -> i1
-!CHECK: %[[AND_YZ:[0-9]+]] = arith.andi %[[CVT_Y]], %[[CVT_Z]] : i1
+!CHECK: %[[AND_YZ:[0-9]+]] = fir.logical_and %[[LOAD_Y]], %[[LOAD_Z]] : !fir.logical<4>
!CHECK: omp.atomic.update memory_order(relaxed) %[[X]]#0 : !fir.ref<!fir.logical<4>> {
!CHECK: ^bb0(%[[ARG:arg[0-9]+]]: !fir.logical<4>):
-!CHECK: %[[CVT_X:[0-9]+]] = fir.convert %[[ARG]] : (!fir.logical<4>) -> i1
-!CHECK: %[[AND_XYZ:[0-9]+]] = arith.andi %[[CVT_X]], %[[AND_YZ]] : i1
-!CHECK: %[[RET:[0-9]+]] = fir.convert %[[AND_XYZ]] : (i1) -> !fir.logical<4>
+!CHECK: %[[RET:[0-9]+]] = fir.logical_and %[[ARG]], %[[AND_YZ]] : !fir.logical<4>
!CHECK: omp.yield(%[[RET]] : !fir.logical<4>)
!CHECK: }
@@ -40,14 +36,10 @@ subroutine f01(x, y, z)
!CHECK: %[[Z:[0-9]+]]:2 = hlfir.declare %arg2
!CHECK: %[[LOAD_Y:[0-9]+]] = fir.load %[[Y]]#0 : !fir.ref<!fir.logical<4>>
!CHECK: %[[LOAD_Z:[0-9]+]] = fir.load %[[Z]]#0 : !fir.ref<!fir.logical<4>>
-!CHECK: %[[CVT_Y:[0-9]+]] = fir.convert %[[LOAD_Y]] : (!fir.logical<4>) -> i1
-!CHECK: %[[CVT_Z:[0-9]+]] = fir.convert %[[LOAD_Z]] : (!fir.logical<4>) -> i1
-!CHECK: %[[OR_YZ:[0-9]+]] = arith.ori %[[CVT_Y]], %[[CVT_Z]] : i1
+!CHECK: %[[OR_YZ:[0-9]+]] = fir.logical_or %[[LOAD_Y]], %[[LOAD_Z]] : !fir.logical<4>
!CHECK: omp.atomic.update memory_order(relaxed) %[[X]]#0 : !fir.ref<!fir.logical<4>> {
!CHECK: ^bb0(%[[ARG:arg[0-9]+]]: !fir.logical<4>):
-!CHECK: %[[CVT_X:[0-9]+]] = fir.convert %[[ARG]] : (!fir.logical<4>) -> i1
-!CHECK: %[[OR_XYZ:[0-9]+]] = arith.ori %[[CVT_X]], %[[OR_YZ]] : i1
-!CHECK: %[[RET:[0-9]+]] = fir.convert %[[OR_XYZ]] : (i1) -> !fir.logical<4>
+!CHECK: %[[RET:[0-9]+]] = fir.logical_or %[[ARG]], %[[OR_YZ]] : !fir.logical<4>
!CHECK: omp.yield(%[[RET]] : !fir.logical<4>)
!CHECK: }
@@ -66,14 +58,10 @@ subroutine f02(x, y, z)
!CHECK: %[[Z:[0-9]+]]:2 = hlfir.declare %arg2
!CHECK: %[[LOAD_Y:[0-9]+]] = fir.load %[[Y]]#0 : !fir.ref<!fir.logical<4>>
!CHECK: %[[LOAD_Z:[0-9]+]] = fir.load %[[Z]]#0 : !fir.ref<!fir.logical<4>>
-!CHECK: %[[CVT_Y:[0-9]+]] = fir.convert %[[LOAD_Y]] : (!fir.logical<4>) -> i1
-!CHECK: %[[CVT_Z:[0-9]+]] = fir.convert %[[LOAD_Z]] : (!fir.logical<4>) -> i1
-!CHECK: %[[EQV_YZ:[0-9]+]] = arith.cmpi eq, %[[CVT_Y]], %[[CVT_Z]] : i1
+!CHECK: %[[EQV_YZ:[0-9]+]] = fir.eqv %[[LOAD_Y]], %[[LOAD_Z]] : !fir.logical<4>
!CHECK: omp.atomic.update memory_order(relaxed) %[[X]]#0 : !fir.ref<!fir.logical<4>> {
!CHECK: ^bb0(%[[ARG:arg[0-9]+]]: !fir.logical<4>):
-!CHECK: %[[CVT_X:[0-9]+]] = fir.convert %[[ARG]] : (!fir.logical<4>) -> i1
-!CHECK: %[[EQV_XYZ:[0-9]+]] = arith.cmpi eq, %[[CVT_X]], %[[EQV_YZ]] : i1
-!CHECK: %[[RET:[0-9]+]] = fir.convert %[[EQV_XYZ]] : (i1) -> !fir.logical<4>
+!CHECK: %[[RET:[0-9]+]] = fir.eqv %[[ARG]], %[[EQV_YZ]] : !fir.logical<4>
!CHECK: omp.yield(%[[RET]] : !fir.logical<4>)
!CHECK: }
@@ -92,14 +80,10 @@ subroutine f03(x, y, z)
!CHECK: %[[Z:[0-9]+]]:2 = hlfir.declare %arg2
!CHECK: %[[LOAD_Y:[0-9]+]] = fir.load %[[Y]]#0 : !fir.ref<!fir.logical<4>>
!CHECK: %[[LOAD_Z:[0-9]+]] = fir.load %[[Z]]#0 : !fir.ref<!fir.logical<4>>
-!CHECK: %[[CVT_Y:[0-9]+]] = fir.convert %[[LOAD_Y]] : (!fir.logical<4>) -> i1
-!CHECK: %[[CVT_Z:[0-9]+]] = fir.convert %[[LOAD_Z]] : (!fir.logical<4>) -> i1
-!CHECK: %[[NEQV_YZ:[0-9]+]] = arith.cmpi ne, %[[CVT_Y]], %[[CVT_Z]] : i1
+!CHECK: %[[NEQV_YZ:[0-9]+]] = fir.neqv %[[LOAD_Y]], %[[LOAD_Z]] : !fir.logical<4>
!CHECK: omp.atomic.update memory_order(relaxed) %[[X]]#0 : !fir.ref<!fir.logical<4>> {
!CHECK: ^bb0(%[[ARG:arg[0-9]+]]: !fir.logical<4>):
-!CHECK: %[[CVT_X:[0-9]+]] = fir.convert %[[ARG]] : (!fir.logical<4>) -> i1
-!CHECK: %[[NEQV_XYZ:[0-9]+]] = arith.cmpi ne, %[[CVT_X]], %[[NEQV_YZ]] : i1
-!CHECK: %[[RET:[0-9]+]] = fir.convert %[[NEQV_XYZ]] : (i1) -> !fir.logical<4>
+!CHECK: %[[RET:[0-9]+]] = fir.neqv %[[ARG]], %[[NEQV_YZ]] : !fir.logical<4>
!CHECK: omp.yield(%[[RET]] : !fir.logical<4>)
!CHECK: }
@@ -120,18 +104,13 @@ subroutine f04(x, a, b, c)
!CHECK: %[[X:[0-9]+]]:2 = hlfir.declare %arg0
!CHECK: %[[LOAD_B:[0-9]+]] = fir.load %[[B]]#0 : !fir.ref<!fir.logical<8>>
!CHECK: %[[LOAD_A:[0-9]+]] = fir.load %[[A]]#0 : !fir.ref<!fir.logical<8>>
-!CHECK: %[[CVT_B:[0-9]+]] = fir.convert %[[LOAD_B]] : (!fir.logical<8>) -> i1
-!CHECK: %[[CVT_A:[0-9]+]] = fir.convert %[[LOAD_A]] : (!fir.logical<8>) -> i1
-!CHECK: %[[AND_BA:[0-9]+]] = arith.andi %[[CVT_B]], %[[CVT_A]] : i1
+!CHECK: %[[AND_BA:[0-9]+]] = fir.logical_and %[[LOAD_B]], %[[LOAD_A]] : !fir.logical<8>
!CHECK: %[[LOAD_C:[0-9]+]] = fir.load %[[C]]#0 : !fir.ref<!fir.logical<8>>
-!CHECK: %[[CVT_C:[0-9]+]] = fir.convert %[[LOAD_C]] : (!fir.logical<8>) -> i1
-!CHECK: %[[AND_BAC:[0-9]+]] = arith.andi %[[AND_BA]], %[[CVT_C]] : i1
+!CHECK: %[[AND_BAC:[0-9]+]] = fir.logical_and %[[AND_BA]], %[[LOAD_C]] : !fir.logical<8>
!CHECK: omp.atomic.update memory_order(relaxed) %[[X]]#0 : !fir.ref<!fir.logical<4>> {
!CHECK: ^bb0(%[[ARG:arg[0-9]+]]: !fir.logical<4>):
!CHECK: %[[CVT8_X:[0-9]+]] = fir.convert %[[ARG]] : (!fir.logical<4>) -> !fir.logical<8>
-!CHECK: %[[CVT_X:[0-9]+]] = fir.convert %[[CVT8_X]] : (!fir.logical<8>) -> i1
-!CHECK: %[[AND_XBAC:[0-9]+]] = arith.andi %[[CVT_X]], %[[AND_BAC]] : i1
-
-!CHECK: %[[RET:[0-9]+]] = fir.convert %[[AND_XBAC]] : (i1) -> !fir.logical<4>
+!CHECK: %[[AND_XBAC:[0-9]+]] = fir.logical_and %[[CVT8_X]], %[[AND_BAC]] : !fir.logical<8>
+!CHECK: %[[RET:[0-9]+]] = fir.convert %[[AND_XBAC]] : (!fir.logical<8>) -> !fir.logical<4>
!CHECK: omp.yield(%[[RET]] : !fir.logical<4>)
!CHECK: }
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90
index fc73fb58d8fd45..87de00faf79168 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90
@@ -18,11 +18,8 @@
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[RES:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4>
-! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[RES:.*]] = fir.logical_and %[[LD0]], %[[LD1]] : !fir.logical<4>
+! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>)
! CHECK: }
@@ -52,11 +49,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_and %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -100,11 +94,8 @@ end subroutine simple_reduction
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_and %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -159,31 +150,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.andi %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.logical_and %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.andi %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.logical_and %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.andi %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.logical_and %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90
index 2cf45938ffb5a0..d8c31cc21d3fd1 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90
@@ -11,11 +11,8 @@
! CHECK-LABEL: } combiner {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>, %[[VAL_1:.*]]: !fir.logical<4>):
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_4:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4>
-! CHECK: omp.yield(%[[VAL_5]] : !fir.logical<4>)
+! CHECK: %[[VAL_4:.*]] = fir.logical_and %[[VAL_0]], %[[VAL_1]] : !fir.logical<4>
+! CHECK: omp.yield(%[[VAL_4]] : !fir.logical<4>)
! CHECK: }
! CHECK-LABEL: func.func @_QPsimple_reduction(
@@ -44,11 +41,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_and %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -92,11 +86,8 @@ end subroutine simple_reduction
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_and %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -151,31 +142,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.andi %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.logical_and %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.andi %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.logical_and %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.andi %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.logical_and %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90
index d2f27badc33020..77f6adaf051298 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90
@@ -18,11 +18,8 @@
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[RES:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4>
-! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[RES:.*]] = fir.eqv %[[LD0]], %[[LD1]] : !fir.logical<4>
+! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>)
! CHECK: }
@@ -52,11 +49,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.eqv %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -99,11 +93,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.eqv %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -158,31 +149,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.cmpi eq, %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.eqv %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.cmpi eq, %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.eqv %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.cmpi eq, %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.eqv %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90
index 7b9b6b847be7dc..d923c1c53be297 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90
@@ -11,11 +11,8 @@
! CHECK-LABEL: } combiner {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>, %[[VAL_1:.*]]: !fir.logical<4>):
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_4:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4>
-! CHECK: omp.yield(%[[VAL_5]] : !fir.logical<4>)
+! CHECK: %[[VAL_4:.*]] = fir.eqv %[[VAL_0]], %[[VAL_1]] : !fir.logical<4>
+! CHECK: omp.yield(%[[VAL_4]] : !fir.logical<4>)
! CHECK: }
! CHECK-LABEL: func.func @_QPsimple_reduction(
@@ -44,11 +41,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.eqv %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -91,11 +85,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.eqv %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -150,31 +141,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.cmpi eq, %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.eqv %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.cmpi eq, %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.eqv %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.cmpi eq, %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.eqv %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90
index 94a24bdeabbff8..6c8f9f43e2bae6 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90
@@ -18,11 +18,8 @@
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[RES:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4>
-! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[RES:.*]] = fir.neqv %[[LD0]], %[[LD1]] : !fir.logical<4>
+! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>)
! CHECK: }
@@ -52,11 +49,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.neqv %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -100,11 +94,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.neqv %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -161,31 +152,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.cmpi ne, %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.neqv %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.cmpi ne, %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.neqv %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.cmpi ne, %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.neqv %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90
index 3f7f97f29afb42..acddc148d5f88d 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90
@@ -11,11 +11,8 @@
! CHECK-LABEL: } combiner {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>, %[[VAL_1:.*]]: !fir.logical<4>):
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_4:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4>
-! CHECK: omp.yield(%[[VAL_5]] : !fir.logical<4>)
+! CHECK: %[[VAL_4:.*]] = fir.neqv %[[VAL_0]], %[[VAL_1]] : !fir.logical<4>
+! CHECK: omp.yield(%[[VAL_4]] : !fir.logical<4>)
! CHECK: }
! CHECK-LABEL: func.func @_QPsimple_reduction(
@@ -44,11 +41,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.neqv %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -92,11 +86,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.neqv %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -153,31 +144,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.cmpi ne, %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.neqv %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.cmpi ne, %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.neqv %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.cmpi ne, %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.neqv %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90
index 4c1496b1f083b9..fbb05d31f8f2d0 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90
@@ -18,11 +18,8 @@
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>):
! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[RES:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4>
-! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[RES:.*]] = fir.logical_or %[[LD0]], %[[LD1]] : !fir.logical<4>
+! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<!fir.logical<4>>
! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>)
! CHECK-LABEL: func.func @_QPsimple_reduction(
@@ -51,11 +48,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_or %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -98,11 +92,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_or %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -157,31 +148,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.ori %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.logical_or %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.ori %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.logical_or %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.ori %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.logical_or %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90
index 6d457f490b9bc0..d2a14c6e13f078 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90
@@ -11,11 +11,8 @@
! CHECK-LABEL: } combiner {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>, %[[VAL_1:.*]]: !fir.logical<4>):
-! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_4:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i1
-! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4>
-! CHECK: omp.yield(%[[VAL_5]] : !fir.logical<4>)
+! CHECK: %[[VAL_4:.*]] = fir.logical_or %[[VAL_0]], %[[VAL_1]] : !fir.logical<4>
+! CHECK: omp.yield(%[[VAL_4]] : !fir.logical<4>)
! CHECK: }
! CHECK-LABEL: func.func @_QPsimple_reduction(
@@ -44,11 +41,8 @@
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64
! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_or %[[VAL_18]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -91,11 +85,8 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_25:.*]] = fir.logical_or %[[VAL_21]], %[[VAL_22]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
@@ -150,31 +141,22 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_37:.*]] = arith.ori %[[VAL_35]], %[[VAL_36]] : i1
-! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_37:.*]] = fir.logical_or %[[VAL_30]], %[[VAL_34]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64
! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_46:.*]] = arith.ori %[[VAL_44]], %[[VAL_45]] : i1
-! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_46:.*]] = fir.logical_or %[[VAL_39]], %[[VAL_43]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_46]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64
! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1
-! CHECK: %[[VAL_55:.*]] = arith.ori %[[VAL_53]], %[[VAL_54]] : i1
-! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4>
-! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_55:.*]] = fir.logical_or %[[VAL_48]], %[[VAL_52]] : !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_55]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: omp.yield
! CHECK: omp.terminator
! CHECK: return
diff --git a/flang/test/Lower/array-elemental-calls-2.f90 b/flang/test/Lower/array-elemental-calls-2.f90
index 86374de477497b..b807a95369f9a7 100644
--- a/flang/test/Lower/array-elemental-calls-2.f90
+++ b/flang/test/Lower/array-elemental-calls-2.f90
@@ -156,11 +156,8 @@ subroutine check_logical_binary_ops()
! CHECK: %[[VAL_38:.*]] = hlfir.designate %{{.*}} (%[[ARG0]]) : (!fir.ref<!fir.array<10x!fir.logical<8>>>, index) -> !fir.ref<!fir.logical<8>>
! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_37]] : !fir.ref<!fir.logical<8>>
! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_38]] : !fir.ref<!fir.logical<8>>
-! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<8>) -> i1
-! CHECK: %[[VAL_42:.*]] = fir.convert %[[VAL_40]] : (!fir.logical<8>) -> i1
-! CHECK: %[[VAL_43:.*]] = arith.cmpi eq, %[[VAL_41]], %[[VAL_42]] : i1
-! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (i1) -> !fir.logical<8>
-! CHECK: hlfir.yield_element %[[VAL_44]] : !fir.logical<8>
+! CHECK: %[[VAL_41:.*]] = fir.eqv %[[VAL_39]], %[[VAL_40]] : !fir.logical<8>
+! CHECK: hlfir.yield_element %[[VAL_41]] : !fir.logical<8>
! CHECK: }
! CHECK: %[[VAL_30:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> {
! CHECK: ^bb0(%[[ARG0:.*]]: index):
diff --git a/flang/test/Transforms/FIRToMemRef/logical.mlir b/flang/test/Transforms/FIRToMemRef/logical.mlir
index 948b8dcb2ae6e7..bfff27f1819bf1 100644
--- a/flang/test/Transforms/FIRToMemRef/logical.mlir
+++ b/flang/test/Transforms/FIRToMemRef/logical.mlir
@@ -28,3 +28,31 @@ func.func @store_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
fir.store %2 to %1 : !fir.ref<!fir.logical<4>>
return
}
+
+// CHECK-LABEL: func.func @logical_and_logical
+// CHECK: fir.logical_and {{.*}} : i32
+func.func @logical_and_logical(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.logical_and %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+
+// CHECK-LABEL: func.func @logical_or_logical
+// CHECK: fir.logical_or {{.*}} : i32
+func.func @logical_or_logical(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.logical_or %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+
+// CHECK-LABEL: func.func @eqv_logical
+// CHECK: fir.eqv {{.*}} : i32
+func.func @eqv_logical(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.eqv %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
+
+// CHECK-LABEL: func.func @neqv_logical
+// CHECK: fir.neqv {{.*}} : i32
+func.func @neqv_logical(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>) -> !fir.logical<4> {
+ %0 = fir.neqv %arg0, %arg1 : !fir.logical<4>
+ return %0 : !fir.logical<4>
+}
>From 608e231f9019462a5995b0ae46af1a8c0cc34143 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Wed, 8 Apr 2026 06:13:45 -0700
Subject: [PATCH 2/2] update folders to actually deal with fir.logical
---
.../flang/Optimizer/Dialect/FIRDialect.td | 1 +
flang/lib/Optimizer/Dialect/FIRDialect.cpp | 10 +++
flang/lib/Optimizer/Dialect/FIROps.cpp | 47 +++++++----
flang/test/Fir/logical-ops-fold.fir | 82 +++++++++++++++++++
4 files changed, 122 insertions(+), 18 deletions(-)
create mode 100644 flang/test/Fir/logical-ops-fold.fir
diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.td b/flang/include/flang/Optimizer/Dialect/FIRDialect.td
index 2ead7348cd4e05..415bf7a6a95fec 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRDialect.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.td
@@ -26,6 +26,7 @@ def FIROpsDialect : Dialect {
let cppNamespace = "::fir";
let useDefaultTypePrinterParser = 0;
let useDefaultAttributePrinterParser = 0;
+ let hasConstantMaterializer = 1;
let dependentDialects = [
// Arith dialect provides FastMathFlagsAttr
// supported by some FIR operations.
diff --git a/flang/lib/Optimizer/Dialect/FIRDialect.cpp b/flang/lib/Optimizer/Dialect/FIRDialect.cpp
index 12f1baf39be458..cfcbc07ec039ad 100644
--- a/flang/lib/Optimizer/Dialect/FIRDialect.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRDialect.cpp
@@ -15,6 +15,7 @@
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "mlir/Transforms/InliningUtils.h"
@@ -71,6 +72,15 @@ void fir::FIROpsDialect::initialize() {
registerOpExternalInterfaces();
}
+mlir::Operation *
+fir::FIROpsDialect::materializeConstant(mlir::OpBuilder &builder,
+ mlir::Attribute value, mlir::Type type,
+ mlir::Location loc) {
+ if (mlir::isa<mlir::IntegerAttr>(value) && mlir::isa<mlir::IntegerType>(type))
+ return mlir::arith::ConstantOp::materialize(builder, value, type, loc);
+ return nullptr;
+}
+
// Register the FIRInlinerInterface to FIROpsDialect
void fir::addFIRInlinerExtension(mlir::DialectRegistry ®istry) {
registry.addExtension(
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index cf0ceed7fbb396..043001bcba1bc0 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1645,30 +1645,38 @@ mlir::OpFoldResult fir::ConvertOp::fold(FoldAdaptor adaptor) {
/// If \p value is a fir.convert of an arith.constant i1, return the i1 value.
static std::optional<bool> getLogicalConstant(mlir::Value value) {
- auto convertOp = value.getDefiningOp<fir::ConvertOp>();
- if (!convertOp)
- return std::nullopt;
- if (auto cst = fir::getIntIfConstant(convertOp.getValue()))
+ mlir::Value maybeConvertInput = value;
+ if (auto convertOp = value.getDefiningOp<fir::ConvertOp>())
+ maybeConvertInput = convertOp.getValue();
+ if (auto cst = fir::getIntIfConstant(maybeConvertInput))
return *cst != 0;
return std::nullopt;
}
-/// Build a logical constant: fir.convert(arith.constant) if the result type
-/// is fir.logical, or arith.constant if it is an integer type.
-static mlir::OpFoldResult logicalConstantFoldResult(mlir::Type resTy,
- bool value) {
- if (mlir::isa<fir::LogicalType>(resTy))
- return {};
- auto intTy = mlir::cast<mlir::IntegerType>(resTy);
- return mlir::IntegerAttr::get(intTy, value ? 1 : 0);
+/// Try to fold a logical binary operation where both operands are constants.
+/// For integer result types, return an IntegerAttr directly (materialized by
+/// the dialect's materializeConstant hook). For fir.logical result types we
+/// cannot create new operations in a folder, so return one of the existing
+/// constant operands if its truth value matches the intended result.
+static mlir::OpFoldResult
+foldLogicalBinaryWithConstants(bool result, mlir::Type resTy, bool lhsCst,
+ mlir::Value lhs, bool rhsCst, mlir::Value rhs) {
+ if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(resTy))
+ return mlir::IntegerAttr::get(intTy, result ? 1 : 0);
+ if (lhsCst == result)
+ return lhs;
+ if (rhsCst == result)
+ return rhs;
+ return {};
}
mlir::OpFoldResult fir::LogicalAndOp::fold(FoldAdaptor adaptor) {
auto lhsCst = getLogicalConstant(getLhs());
auto rhsCst = getLogicalConstant(getRhs());
if (lhsCst && rhsCst)
- return logicalConstantFoldResult(getType(), *lhsCst && *rhsCst);
- // land(x, true) -> x
+ return foldLogicalBinaryWithConstants(*lhsCst && *rhsCst, getType(),
+ *lhsCst, getLhs(), *rhsCst, getRhs());
+ // logical_and(x, true) -> x
if (rhsCst && *rhsCst)
return getLhs();
if (lhsCst && *lhsCst)
@@ -1680,8 +1688,9 @@ mlir::OpFoldResult fir::LogicalOrOp::fold(FoldAdaptor adaptor) {
auto lhsCst = getLogicalConstant(getLhs());
auto rhsCst = getLogicalConstant(getRhs());
if (lhsCst && rhsCst)
- return logicalConstantFoldResult(getType(), *lhsCst || *rhsCst);
- // lor(x, false) -> x
+ return foldLogicalBinaryWithConstants(*lhsCst || *rhsCst, getType(),
+ *lhsCst, getLhs(), *rhsCst, getRhs());
+ // logical_or(x, false) -> x
if (rhsCst && !*rhsCst)
return getLhs();
if (lhsCst && !*lhsCst)
@@ -1693,7 +1702,8 @@ mlir::OpFoldResult fir::EqvOp::fold(FoldAdaptor adaptor) {
auto lhsCst = getLogicalConstant(getLhs());
auto rhsCst = getLogicalConstant(getRhs());
if (lhsCst && rhsCst)
- return logicalConstantFoldResult(getType(), *lhsCst == *rhsCst);
+ return foldLogicalBinaryWithConstants(*lhsCst == *rhsCst, getType(),
+ *lhsCst, getLhs(), *rhsCst, getRhs());
// eqv(x, true) -> x
if (rhsCst && *rhsCst)
return getLhs();
@@ -1706,7 +1716,8 @@ mlir::OpFoldResult fir::NeqvOp::fold(FoldAdaptor adaptor) {
auto lhsCst = getLogicalConstant(getLhs());
auto rhsCst = getLogicalConstant(getRhs());
if (lhsCst && rhsCst)
- return logicalConstantFoldResult(getType(), *lhsCst != *rhsCst);
+ return foldLogicalBinaryWithConstants(*lhsCst != *rhsCst, getType(),
+ *lhsCst, getLhs(), *rhsCst, getRhs());
// neqv(x, false) -> x
if (rhsCst && !*rhsCst)
return getLhs();
diff --git a/flang/test/Fir/logical-ops-fold.fir b/flang/test/Fir/logical-ops-fold.fir
new file mode 100644
index 00000000000000..016e8f46c2ab26
--- /dev/null
+++ b/flang/test/Fir/logical-ops-fold.fir
@@ -0,0 +1,82 @@
+// RUN: fir-opt --canonicalize %s | FileCheck %s
+
+// logical_and(false, false) == false
+// CHECK-LABEL: @fold_logical_and_false_false
+func.func @fold_logical_and_false_false() -> !fir.logical<4> {
+ %false = arith.constant false
+ %lhs = fir.convert %false : (i1) -> !fir.logical<4>
+ %rhs = fir.convert %false : (i1) -> !fir.logical<4>
+ %res = fir.logical_and %lhs, %rhs : !fir.logical<4>
+ // CHECK-NOT: fir.logical_and
+ // CHECK: %[[FALSE:.*]] = fir.convert
+ // CHECK: return %[[FALSE]] : !fir.logical<4>
+ return %res : !fir.logical<4>
+}
+
+// logical_and(true, false) == false
+// CHECK-LABEL: @fold_logical_and_true_false
+func.func @fold_logical_and_true_false() -> !fir.logical<4> {
+ %true = arith.constant true
+ %false = arith.constant false
+ %lhs = fir.convert %true : (i1) -> !fir.logical<4>
+ %rhs = fir.convert %false : (i1) -> !fir.logical<4>
+ %res = fir.logical_and %lhs, %rhs : !fir.logical<4>
+ // CHECK-NOT: fir.logical_and
+ // CHECK: %[[FALSE:.*]] = arith.constant false
+ // CHECK: %[[RHS:.*]] = fir.convert %[[FALSE]] : (i1) -> !fir.logical<4>
+ // CHECK: return %[[RHS]] : !fir.logical<4>
+ return %res : !fir.logical<4>
+}
+
+// logical_and(x, true) -> x
+// CHECK-LABEL: @fold_logical_and_identity
+// CHECK-SAME: (%[[X:.*]]: !fir.logical<4>)
+func.func @fold_logical_and_identity(%x: !fir.logical<4>) -> !fir.logical<4> {
+ %true = arith.constant true
+ %rhs = fir.convert %true : (i1) -> !fir.logical<4>
+ %res = fir.logical_and %x, %rhs : !fir.logical<4>
+ // CHECK-NOT: fir.logical_and
+ // CHECK: return %[[X]] : !fir.logical<4>
+ return %res : !fir.logical<4>
+}
+
+// logical_or(true, false) == true
+// CHECK-LABEL: @fold_logical_or_true_false
+func.func @fold_logical_or_true_false() -> !fir.logical<4> {
+ %true = arith.constant true
+ %false = arith.constant false
+ %lhs = fir.convert %true : (i1) -> !fir.logical<4>
+ %rhs = fir.convert %false : (i1) -> !fir.logical<4>
+ %res = fir.logical_or %lhs, %rhs : !fir.logical<4>
+ // CHECK-NOT: fir.logical_or
+ // CHECK: %[[TRUE:.*]] = arith.constant true
+ // CHECK: %[[LHS:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4>
+ // CHECK: return %[[LHS]] : !fir.logical<4>
+ return %res : !fir.logical<4>
+}
+
+// logical_or(x, false) -> x
+// CHECK-LABEL: @fold_logical_or_identity
+// CHECK-SAME: (%[[X:.*]]: !fir.logical<4>)
+func.func @fold_logical_or_identity(%x: !fir.logical<4>) -> !fir.logical<4> {
+ %false = arith.constant false
+ %rhs = fir.convert %false : (i1) -> !fir.logical<4>
+ %res = fir.logical_or %x, %rhs : !fir.logical<4>
+ // CHECK-NOT: fir.logical_or
+ // CHECK: return %[[X]] : !fir.logical<4>
+ return %res : !fir.logical<4>
+}
+
+// Fold on integer type: logical_and(1, 0) -> arith.constant 0 : i32
+// CHECK-LABEL: @fold_logical_and_int
+func.func @fold_logical_and_int() -> i32 {
+ %c1 = arith.constant 1 : i1
+ %c0 = arith.constant 0 : i1
+ %lhs = fir.convert %c1 : (i1) -> i32
+ %rhs = fir.convert %c0 : (i1) -> i32
+ %res = fir.logical_and %lhs, %rhs : i32
+ // CHECK-NOT: fir.logical_and
+ // CHECK: %[[C:.*]] = arith.constant 0 : i32
+ // CHECK: return %[[C]] : i32
+ return %res : i32
+}
More information about the flang-commits
mailing list