[flang-commits] [flang] be3b40c - [flang] Lower basic binary operation for scalars

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Fri Feb 18 06:50:38 PST 2022


Author: Valentin Clement
Date: 2022-02-18T15:50:31+01:00
New Revision: be3b40c059355115a8041f5bd866ad8d99950611

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

LOG: [flang] Lower basic binary operation for scalars

Lower simple binary operation (+, -, *, /) for scalars.

This patch is part of the upstreaming effort from fir-dev branch.

Depends on D120058

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D120063

Co-authored-by: Jean Perier <jperier at nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>

Added: 
    

Modified: 
    flang/lib/Lower/ConvertExpr.cpp
    flang/test/Lower/assignment.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 466a74fe031eb..07e5fb8fa1a57 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -206,12 +206,27 @@ class ScalarExprLowering {
     return builder.create<fir::NegcOp>(getLoc(), genunbox(op.left()));
   }
 
+  template <typename OpTy>
+  mlir::Value createBinaryOp(const ExtValue &left, const ExtValue &right) {
+    assert(fir::isUnboxedValue(left) && fir::isUnboxedValue(right));
+    mlir::Value lhs = fir::getBase(left);
+    mlir::Value rhs = fir::getBase(right);
+    assert(lhs.getType() == rhs.getType() && "types must be the same");
+    return builder.create<OpTy>(getLoc(), lhs, rhs);
+  }
+
+  template <typename OpTy, typename A>
+  mlir::Value createBinaryOp(const A &ex) {
+    ExtValue left = genval(ex.left());
+    return createBinaryOp<OpTy>(left, genval(ex.right()));
+  }
+
 #undef GENBIN
 #define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp)                           \
   template <int KIND>                                                          \
   ExtValue genval(const Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type< \
                       Fortran::common::TypeCategory::GenBinTyCat, KIND>> &x) { \
-    TODO(getLoc(), "genval GenBinEvOp");                                       \
+    return createBinaryOp<GenBinFirOp>(x);                                     \
   }
 
   GENBIN(Add, Integer, mlir::arith::AddIOp)

diff  --git a/flang/test/Lower/assignment.f90 b/flang/test/Lower/assignment.f90
index 32c2086de7de2..ce9689a708a8f 100644
--- a/flang/test/Lower/assignment.f90
+++ b/flang/test/Lower/assignment.f90
@@ -63,5 +63,195 @@ real function negr(a)
 ! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         %[[NEG:.*]] = fir.negc %[[A_VAL]] : !fir.complex<4>
 ! CHECK:         fir.store %[[NEG]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+
+integer function addi(a, b)
+  integer :: a, b
+  addi = a + b
+end
+
+! CHECK-LABEL: func @_QPaddi(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca i32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+! CHECK:         %[[ADD:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
+! CHECK:         fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         return %[[RET]] : i32
+
+integer function subi(a, b)
+  integer :: a, b
+  subi = a - b
+end
+
+! CHECK-LABEL: func @_QPsubi(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca i32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+! CHECK:         %[[SUB:.*]] = arith.subi %[[A_VAL]], %[[B_VAL]] : i32
+! CHECK:         fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         return %[[RET]] : i32
+
+integer function muli(a, b)
+  integer :: a, b
+  muli = a * b
+end
+
+! CHECK-LABEL: func @_QPmuli(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca i32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+! CHECK:         %[[MUL:.*]] = arith.muli %[[A_VAL]], %[[B_VAL]] : i32
+! CHECK:         fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         return %[[RET]] : i32
+
+integer function divi(a, b)
+  integer :: a, b
+  divi = a / b
+end
+
+! CHECK-LABEL: func @_QPdivi(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca i32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+! CHECK:         %[[DIV:.*]] = arith.divsi %[[A_VAL]], %[[B_VAL]] : i32
+! CHECK:         fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<i32>
+! CHECK:         return %[[RET]] : i32
+
+real function addf(a, b)
+  real :: a, b
+  addf = a + b
+end
+
+! CHECK-LABEL: func @_QPaddf(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca f32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<f32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<f32>
+! CHECK:         %[[ADD:.*]] = arith.addf %[[A_VAL]], %[[B_VAL]] : f32
+! CHECK:         fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         return %[[RET]] : f32
+
+real function subf(a, b)
+  real :: a, b
+  subf = a - b
+end
+
+! CHECK-LABEL: func @_QPsubf(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca f32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<f32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<f32>
+! CHECK:         %[[SUB:.*]] = arith.subf %[[A_VAL]], %[[B_VAL]] : f32
+! CHECK:         fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         return %[[RET]] : f32
+
+real function mulf(a, b)
+  real :: a, b
+  mulf = a * b
+end
+
+! CHECK-LABEL: func @_QPmulf(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca f32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<f32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<f32>
+! CHECK:         %[[MUL:.*]] = arith.mulf %[[A_VAL]], %[[B_VAL]] : f32
+! CHECK:         fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         return %[[RET]] : f32
+
+real function divf(a, b)
+  real :: a, b
+  divf = a / b
+end
+
+! CHECK-LABEL: func @_QPdivf(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca f32
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<f32>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<f32>
+! CHECK:         %[[DIV:.*]] = arith.divf %[[A_VAL]], %[[B_VAL]] : f32
+! CHECK:         fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<f32>
+! CHECK:         return %[[RET]] : f32
+
+complex function addc(a, b)
+  complex :: a, b
+  addc = a + b
+end
+
+! CHECK-LABEL: func @_QPaddc(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca !fir.complex<4>
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[ADD:.*]] = fir.addc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4>
+! CHECK:         fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         return %[[RET]] : !fir.complex<4>
+
+complex function subc(a, b)
+  complex :: a, b
+  subc = a - b
+end
+
+! CHECK-LABEL: func @_QPsubc(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca !fir.complex<4>
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[SUB:.*]] = fir.subc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4>
+! CHECK:         fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         return %[[RET]] : !fir.complex<4>
+
+complex function mulc(a, b)
+  complex :: a, b
+  mulc = a * b
+end
+
+! CHECK-LABEL: func @_QPmulc(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca !fir.complex<4>
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[MUL:.*]] = fir.mulc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4>
+! CHECK:         fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<!fir.complex<4>>
+! CHECK:         return %[[RET]] : !fir.complex<4>
+
+complex function divc(a, b)
+  complex :: a, b
+  divc = a / b
+end
+
+! CHECK-LABEL: func @_QPdivc(
+! CHECK-SAME:    %[[A:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "a"},
+! CHECK-SAME:    %[[B:.*]]: !fir.ref<!fir.complex<4>> {fir.bindc_name = "b"}
+! CHECK:         %[[FCTRES:.*]] = fir.alloca !fir.complex<4>
+! CHECK:         %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<!fir.complex<4>>
+! CHECK:         %[[DIV:.*]] = fir.divc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4>
+! CHECK:         fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         return %[[RET]] : !fir.complex<4>


        


More information about the flang-commits mailing list