From: Valentin Clement Date: Fri, 25 Feb 2022 20:05:09 +0000 (+0100) Subject: [flang] Lower logical comparison and logical operations X-Git-Tag: upstream/15.0.7~15239 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a7ac120a9ad784998a5527fc0a71b2d0fd55eccb;p=platform%2Fupstream%2Fllvm.git [flang] Lower logical comparison and logical operations This handles the lowering of the logical comparison to `arith.cmpi` operation. The logical operations `.OR.`, `.AND.` and `.NOT.` are lowered to `arith.ori`, `arith.andi` and `arith.xori` This patch is part of the upstreaming effort from fir-dev branch. Depends on D120559 Reviewed By: schweitz, rovka Differential Revision: https://reviews.llvm.org/D120560 Co-authored-by: Eric Schweitz Co-authored-by: Jean Perier --- diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index 3f02d72..12e2928 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -612,12 +612,36 @@ public: template ExtValue genval(const Fortran::evaluate::Not &op) { - TODO(getLoc(), "genval Not"); + mlir::Value logical = genunbox(op.left()); + mlir::Value one = genBoolConstant(true); + mlir::Value val = + builder.createConvert(getLoc(), builder.getI1Type(), logical); + return builder.create(getLoc(), val, one); } template ExtValue genval(const Fortran::evaluate::LogicalOperation &op) { - TODO(getLoc(), "genval LogicalOperation"); + mlir::IntegerType i1Type = builder.getI1Type(); + mlir::Value slhs = genunbox(op.left()); + mlir::Value srhs = genunbox(op.right()); + mlir::Value lhs = builder.createConvert(getLoc(), i1Type, slhs); + mlir::Value rhs = builder.createConvert(getLoc(), i1Type, srhs); + switch (op.logicalOperator) { + case Fortran::evaluate::LogicalOperator::And: + return createBinaryOp(lhs, rhs); + case Fortran::evaluate::LogicalOperator::Or: + return createBinaryOp(lhs, rhs); + case Fortran::evaluate::LogicalOperator::Eqv: + return createCompareOp( + mlir::arith::CmpIPredicate::eq, lhs, rhs); + case Fortran::evaluate::LogicalOperator::Neqv: + return createCompareOp( + mlir::arith::CmpIPredicate::ne, lhs, rhs); + case Fortran::evaluate::LogicalOperator::Not: + // lib/evaluate expression for .NOT. is Fortran::evaluate::Not. + llvm_unreachable(".NOT. is not a binary operator"); + } + llvm_unreachable("unhandled logical operation"); } /// Convert a scalar literal constant to IR. diff --git a/flang/test/Lower/logical-operations.f90 b/flang/test/Lower/logical-operations.f90 new file mode 100644 index 0000000..9ade97b --- /dev/null +++ b/flang/test/Lower/logical-operations.f90 @@ -0,0 +1,65 @@ +! RUN: bbc %s -o "-" | FileCheck %s + +! Test logical intrinsic operation lowering to fir. + +! CHECK-LABEL:eqv0_test +LOGICAL(1) FUNCTION eqv0_test(x0, x1) +LOGICAL(1) :: x0 +LOGICAL(1) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK-DAG:[[reg3:%[0-9]+]] = fir.convert [[reg1]] {{.*}} -> i1 +! CHECK-DAG:[[reg4:%[0-9]+]] = fir.convert [[reg2]] {{.*}} -> i1 +! CHECK:[[reg5:%[0-9]+]] = arith.cmpi eq, [[reg3]], [[reg4]] +! CHECK:fir.convert [[reg5]] {{.*}} -> !fir.logical<1> +eqv0_test = x0 .EQV. x1 +END FUNCTION + +! CHECK-LABEL:neqv1_test +LOGICAL(1) FUNCTION neqv1_test(x0, x1) +LOGICAL(1) :: x0 +LOGICAL(1) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK-DAG:[[reg3:%[0-9]+]] = fir.convert [[reg1]] {{.*}} -> i1 +! CHECK-DAG:[[reg4:%[0-9]+]] = fir.convert [[reg2]] {{.*}} -> i1 +! CHECK:[[reg5:%[0-9]+]] = arith.cmpi ne, [[reg3]], [[reg4]] +! CHECK:fir.convert [[reg5]] {{.*}} -> !fir.logical<1> +neqv1_test = x0 .NEQV. x1 +END FUNCTION + +! CHECK-LABEL:or2_test +LOGICAL(1) FUNCTION or2_test(x0, x1) +LOGICAL(1) :: x0 +LOGICAL(1) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK-DAG:[[reg3:%[0-9]+]] = fir.convert [[reg1]] {{.*}} -> i1 +! CHECK-DAG:[[reg4:%[0-9]+]] = fir.convert [[reg2]] {{.*}} -> i1 +! CHECK:[[reg5:%[0-9]+]] = arith.ori [[reg3]], [[reg4]] +! CHECK:fir.convert [[reg5]] {{.*}} -> !fir.logical<1> +or2_test = x0 .OR. x1 +END FUNCTION + +! CHECK-LABEL:and3_test +LOGICAL(1) FUNCTION and3_test(x0, x1) +LOGICAL(1) :: x0 +LOGICAL(1) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK-DAG:[[reg3:%[0-9]+]] = fir.convert [[reg1]] {{.*}} -> i1 +! CHECK-DAG:[[reg4:%[0-9]+]] = fir.convert [[reg2]] {{.*}} -> i1 +! CHECK:[[reg5:%[0-9]+]] = arith.andi [[reg3]], [[reg4]] +! CHECK:fir.convert [[reg5]] {{.*}} -> !fir.logical<1> +and3_test = x0 .AND. x1 +END FUNCTION + +! CHECK-LABEL:not4_test +LOGICAL(1) FUNCTION not4_test(x0) +LOGICAL(1) :: x0 +! CHECK:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK:[[reg2:%[0-9]+]] = fir.convert [[reg1]] {{.*}} -> i1 +! CHECK:[[reg3:%[0-9]+]] = arith.xori [[reg2]], %true +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<1> +not4_test = .NOT. x0 +END FUNCTION