[flang-commits] [flang] 74af5fa - [flang] preserve logical operations in single FIR operation (#190771)

via flang-commits flang-commits at lists.llvm.org
Thu Apr 9 09:52:35 PDT 2026


Author: jeanPerier
Date: 2026-04-09T18:52:30+02:00
New Revision: 74af5fa55f8f6f96e9d01edfd2beaf9b245dfda1

URL: https://github.com/llvm/llvm-project/commit/74af5fa55f8f6f96e9d01edfd2beaf9b245dfda1
DIFF: https://github.com/llvm/llvm-project/commit/74af5fa55f8f6f96e9d01edfd2beaf9b245dfda1.diff

LOG: [flang] preserve logical operations in single FIR operation (#190771)

This patch adds new operations to represent AND/OR/EQV/NEQV logical
operation with the main goal of preserving them at a higher level in the
IR to make it easier to match them and to dispatch them to atomic
implementations when working on reductions.

They are only generated when one of the argument is actually a logical,
otherwise, the when dealing with AND/OR... where both operands are
comparisons, the i1 arith operations are still generated since using the
new operation would make the IR more complex and preserving logical
operation is only valuable when one of the operand is a logical
variable.

Added: 
    flang/test/Fir/logical-ops-fold.fir

Modified: 
    flang/include/flang/Optimizer/Dialect/FIRDialect.td
    flang/include/flang/Optimizer/Dialect/FIROps.td
    flang/include/flang/Optimizer/Dialect/FIRTypes.td
    flang/lib/Lower/ConvertExprToHLFIR.cpp
    flang/lib/Lower/Support/ReductionProcessor.cpp
    flang/lib/Optimizer/CodeGen/CodeGen.cpp
    flang/lib/Optimizer/Dialect/FIRDialect.cpp
    flang/lib/Optimizer/Dialect/FIROps.cpp
    flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
    flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
    flang/test/Fir/fir-ops.fir
    flang/test/Fir/invalid.fir
    flang/test/Fir/logical-convert.fir
    flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
    flang/test/Lower/HLFIR/binary-ops.f90
    flang/test/Lower/HLFIR/expr-box.f90
    flang/test/Lower/HLFIR/user-defined-assignment.f90
    flang/test/Lower/OpenACC/acc-reduction.f90
    flang/test/Lower/OpenMP/atomic-update-reassoc-logical.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90
    flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90
    flang/test/Lower/array-elemental-calls-2.f90
    flang/test/Transforms/FIRToMemRef/logical.mlir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.td b/flang/include/flang/Optimizer/Dialect/FIRDialect.td
index 2ead7348cd4e0..415bf7a6a95fe 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/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index f499be9fb5dd2..02cda7f875437 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, !listconcat(traits, [Pure])>,
+      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 7c7fe706d29d4..c58d75851349e 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 7ddd09e59c262..5ee409b031357 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 e0cba4c512258..04efba463de49 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 e2cf0989ae2f0..7c3f686fc58bb 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;
 
@@ -4304,6 +4313,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;
 
@@ -4653,19 +4771,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/FIRDialect.cpp b/flang/lib/Optimizer/Dialect/FIRDialect.cpp
index 12f1baf39be45..cfcbc07ec039a 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 &registry) {
   registry.addExtension(

diff  --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index b5e767ef3030b..e2ba1f1c1f4ec 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1639,6 +1639,93 @@ 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) {
+  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;
+}
+
+/// 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 foldLogicalBinaryWithConstants(*lhsCst && *rhsCst, getType(),
+                                          *lhsCst, getLhs(), *rhsCst, getRhs());
+  // logical_and(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 foldLogicalBinaryWithConstants(*lhsCst || *rhsCst, getType(),
+                                          *lhsCst, getLhs(), *rhsCst, getRhs());
+  // logical_or(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 foldLogicalBinaryWithConstants(*lhsCst == *rhsCst, getType(),
+                                          *lhsCst, getLhs(), *rhsCst, getRhs());
+  // 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 foldLogicalBinaryWithConstants(*lhsCst != *rhsCst, getType(),
+                                          *lhsCst, getLhs(), *rhsCst, getRhs());
+  // 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 25af35513d18d..28d46774b3d10 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 144ef9c723398..07a87a490002f 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"
@@ -1086,6 +1087,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");
 
@@ -1104,10 +1128,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 c9ba08a5a47c8..2dd220134a73d 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 9ab5e4f8553d1..5471bcd8acc29 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 
diff erent 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 4cc081934db43..cf07480e641a9 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/Fir/logical-ops-fold.fir b/flang/test/Fir/logical-ops-fold.fir
new file mode 100644
index 0000000000000..016e8f46c2ab2
--- /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
+}

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 6fcd942f4a1e5..6f300b8dfaa43 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 3a83cd44d3c2e..dffd67a247075 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 4631d18e481bd..2cc46666b71fb 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 2dffd92ca50f5..13e1f2fde9558 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 49789efc545ba..a1f20d777cee2 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 ccde4fed12f2f..564f0f9bd5fa3 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 fc73fb58d8fd4..87de00faf7916 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 2cf45938ffb5a..d8c31cc21d3fd 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 d2f27badc3302..77f6adaf05129 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 7b9b6b847be7d..d923c1c53be29 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 94a24bdeabbff..6c8f9f43e2bae 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 3f7f97f29afb4..acddc148d5f88 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 4c1496b1f083b..fbb05d31f8f2d 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 6d457f490b9bc..d2a14c6e13f07 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 86374de477497..b807a95369f9a 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 948b8dcb2ae6e..bfff27f1819bf 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>
+}


        


More information about the flang-commits mailing list