Skip to content

Commit

Permalink
[flang][hlfir] Fixed hlfir.assign codegen for polymorphic LHS.
Browse files Browse the repository at this point in the history
The RHS cannot be casted to the LHS type, when LHS is polymorphic.
With this change we will use the RHS type for emboxing with special
hadling for i1 type.

I created #62419 for the
AllocaOp generated during HLFIRtoFir conversion.

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D149392
  • Loading branch information
vzakhari committed Apr 28, 2023
1 parent 6f01cb9 commit 8c8fe11
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
22 changes: 16 additions & 6 deletions flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,22 @@ class AssignOpConversion : public mlir::OpRewritePattern<hlfir::AssignOp> {
if (rhsIsValue) {
// createBox can only be called for fir::ExtendedValue that are
// already in memory. Place the integer/real/complex/logical scalar
// in memory (convert to the LHS type so that i1 are allocated in
// a proper Fortran logical storage).
mlir::Type lhsValueType = lhs.getFortranElementType();
mlir::Value rhsVal =
builder.createConvert(loc, lhsValueType, fir::getBase(rhsExv));
mlir::Value temp = builder.create<fir::AllocaOp>(loc, lhsValueType);
// in memory.
// The RHS might be i1, which is not supported for emboxing.
// If LHS is not polymorphic, we may cast the RHS to the LHS type
// before emboxing. If LHS is polymorphic we have to figure out
// the data type for RHS emboxing anyway.
// It is probably a good idea to make sure that the data type
// of the RHS is always a valid Fortran storage data type.
// For the time being, just handle i1 explicitly here.
mlir::Type rhsType = rhs.getFortranElementType();
mlir::Value rhsVal = fir::getBase(rhsExv);
if (rhsType == builder.getI1Type()) {
rhsType = fir::LogicalType::get(builder.getContext(), 4);
rhsVal = builder.createConvert(loc, rhsType, rhsVal);
}

mlir::Value temp = builder.create<fir::AllocaOp>(loc, rhsType);
builder.create<fir::StoreOp>(loc, rhsVal, temp);
rhsExv = temp;
}
Expand Down
39 changes: 39 additions & 0 deletions flang/test/HLFIR/assign-codegen.fir
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,42 @@ func.func @test_alloc_assign_polymorphic(%lhs: !fir.ref<!fir.class<!fir.heap<!fi
// CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<t>>>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_1]] : (!fir.class<!fir.array<?x!fir.type<t>>>) -> !fir.box<none>
// CHECK: %[[VAL_10:.*]] = fir.call @_FortranAAssignPolymorphic(%[[VAL_7]], %[[VAL_8]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none

func.func @assing_scalar_int_to_polymorphic(%arg0: !fir.ref<!fir.class<!fir.heap<none>>>) {
%c123_i32 = arith.constant 123 : i32
%0:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "x"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>)
hlfir.assign %c123_i32 to %0#0 realloc : i32, !fir.ref<!fir.class<!fir.heap<none>>>
return
}

// CHECK-LABEL: func.func @assing_scalar_int_to_polymorphic(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<none>>>) {
// CHECK: %[[VAL_1:.*]] = arith.constant 123 : i32
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "x"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.class<!fir.heap<none>>>
// CHECK: %[[VAL_3:.*]] = fir.alloca i32
// CHECK: fir.store %[[VAL_1]] to %[[VAL_3]] : !fir.ref<i32>
// CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_4]] : (!fir.box<i32>) -> !fir.box<none>
// CHECK: %[[VAL_11:.*]] = fir.call @_FortranAAssignPolymorphic(%[[VAL_8]], %[[VAL_9]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none

func.func @assign_i1_to_polymorphic(%arg0: !fir.ref<!fir.class<!fir.heap<none>>>) {
%false = arith.constant false
%0:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "x"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>)
%1 = hlfir.no_reassoc %false : i1
hlfir.assign %1 to %0#0 realloc : i1, !fir.ref<!fir.class<!fir.heap<none>>>
return
}

// CHECK-LABEL: func.func @assign_i1_to_polymorphic(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<none>>>) {
// CHECK: %[[VAL_1:.*]] = arith.constant false
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "x"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.class<!fir.heap<none>>>
// CHECK: %[[VAL_3:.*]] = fir.no_reassoc %[[VAL_1]] : i1
// CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4>
// CHECK: %[[VAL_5:.*]] = fir.alloca !fir.logical<4>
// CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.logical<4>>
// CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_5]] : (!fir.ref<!fir.logical<4>>) -> !fir.box<!fir.logical<4>>
// CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_6]] : (!fir.box<!fir.logical<4>>) -> !fir.box<none>
// CHECK: %[[VAL_13:.*]] = fir.call @_FortranAAssignPolymorphic(%[[VAL_10]], %[[VAL_11]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none

0 comments on commit 8c8fe11

Please sign in to comment.