diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -206,12 +206,27 @@ return builder.create(getLoc(), genunbox(op.left())); } + template + 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(getLoc(), lhs, rhs); + } + + template + mlir::Value createBinaryOp(const A &ex) { + ExtValue left = genval(ex.left()); + return createBinaryOp(left, genval(ex.right())); + } + #undef GENBIN #define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp) \ template \ ExtValue genval(const Fortran::evaluate::GenBinEvOp> &x) { \ - TODO(getLoc(), "genval GenBinEvOp"); \ + return createBinaryOp(x); \ } GENBIN(Add, Integer, mlir::arith::AddIOp) diff --git a/flang/test/Lower/assignment.f90 b/flang/test/Lower/assignment.f90 --- a/flang/test/Lower/assignment.f90 +++ b/flang/test/Lower/assignment.f90 @@ -63,5 +63,195 @@ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> ! CHECK: %[[NEG:.*]] = fir.negc %[[A_VAL]] : !fir.complex<4> ! CHECK: fir.store %[[NEG]] to %[[FCTRES]] : !fir.ref> + +integer function addi(a, b) + integer :: a, b + addi = a + b +end + +! CHECK-LABEL: func @_QPaddi( +! CHECK-SAME: %[[A:.*]]: !fir.ref {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca i32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[ADD:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32 +! CHECK: fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca i32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[SUB:.*]] = arith.subi %[[A_VAL]], %[[B_VAL]] : i32 +! CHECK: fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca i32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[MUL:.*]] = arith.muli %[[A_VAL]], %[[B_VAL]] : i32 +! CHECK: fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca i32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[DIV:.*]] = arith.divsi %[[A_VAL]], %[[B_VAL]] : i32 +! CHECK: fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca f32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[ADD:.*]] = arith.addf %[[A_VAL]], %[[B_VAL]] : f32 +! CHECK: fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca f32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[SUB:.*]] = arith.subf %[[A_VAL]], %[[B_VAL]] : f32 +! CHECK: fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca f32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[MUL:.*]] = arith.mulf %[[A_VAL]], %[[B_VAL]] : f32 +! CHECK: fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca f32 +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref +! CHECK: %[[DIV:.*]] = arith.divf %[[A_VAL]], %[[B_VAL]] : f32 +! CHECK: fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref +! 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.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca !fir.complex<4> +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref> +! CHECK: %[[ADD:.*]] = fir.addc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4> +! CHECK: fir.store %[[ADD]] to %[[FCTRES]] : !fir.ref> +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref> +! 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.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca !fir.complex<4> +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref> +! CHECK: %[[SUB:.*]] = fir.subc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4> +! CHECK: fir.store %[[SUB]] to %[[FCTRES]] : !fir.ref> +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref> +! 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.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca !fir.complex<4> +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref> +! CHECK: %[[MUL:.*]] = fir.mulc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4> +! CHECK: fir.store %[[MUL]] to %[[FCTRES]] : !fir.ref> +! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref> +! 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.bindc_name = "a"}, +! CHECK-SAME: %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"} +! CHECK: %[[FCTRES:.*]] = fir.alloca !fir.complex<4> +! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> +! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref> +! CHECK: %[[DIV:.*]] = fir.divc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4> +! CHECK: fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref> ! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref> ! CHECK: return %[[RET]] : !fir.complex<4>