[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 ®istry) {
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