-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][hlfir] address char_convert issues as mentioned in #64315 #67570
Conversation
@llvm/pr-subscribers-flang-fir-hlfir ChangesDraft PR message:
@vzakhari @jeanPerier I borrowed a helper function from HLFIRTools.cpp. The function is Thanks, Full diff: https://github.com/llvm/llvm-project/pull/67570.diff 2 Files Affected:
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index bc98fdd917d41d0..7fed9dc5c08868e 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1403,6 +1403,22 @@ struct UnaryOp<Fortran::evaluate::Parentheses<T>> {
}
};
+static fir::CharBoxValue genUnboxChar(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ mlir::Value boxChar) {
+ if (auto emboxChar = boxChar.getDefiningOp<fir::EmboxCharOp>())
+ return {emboxChar.getMemref(), emboxChar.getLen()};
+ mlir::Type refType = fir::ReferenceType::get(
+ boxChar.getType().cast<fir::BoxCharType>().getEleTy());
+ auto unboxed = builder.create<fir::UnboxCharOp>(
+ loc, refType, builder.getIndexType(), boxChar);
+ mlir::Value addr = unboxed.getResult(0);
+ mlir::Value len = unboxed.getResult(1);
+ if (auto varIface = boxChar.getDefiningOp<fir::FortranVariableOpInterface>())
+ if (mlir::Value explicitlen = varIface.getExplicitCharLen())
+ len = explicitlen;
+ return {addr, len};
+}
template <Fortran::common::TypeCategory TC1, int KIND,
Fortran::common::TypeCategory TC2>
struct UnaryOp<
@@ -1414,7 +1430,6 @@ struct UnaryOp<
hlfir::Entity lhs) {
if constexpr (TC1 == Fortran::common::TypeCategory::Character &&
TC2 == TC1) {
- // TODO(loc, "character conversion in HLFIR");
auto kindMap = builder.getKindMap();
mlir::Type fromTy = lhs.getFortranElementType();
mlir::Value origBufferSize = genCharLength(loc, builder, lhs);
@@ -1435,8 +1450,15 @@ struct UnaryOp<
// allocate space on the stack for toBuffer
auto dest = builder.create<fir::AllocaOp>(loc, toTy,
mlir::ValueRange{bufferSize});
- builder.create<fir::CharConvertOp>(loc, lhs.getFirBase(), origBufferSize,
- dest);
+ auto src = lhs.getFirBase();
+ if (lhs.getType().isa<hlfir::ExprType>()) {
+ if (auto asExpr = lhs.getDefiningOp<hlfir::AsExprOp>()) {
+ src = asExpr.getVar();
+ }
+ } else if (lhs.getType().isa<fir::BoxCharType>())
+ if (!lhs.getDefiningOp<hlfir::DeclareOp>())
+ src = genUnboxChar(loc, builder, lhs).getAddr();
+ builder.create<fir::CharConvertOp>(loc, src, origBufferSize, dest);
return hlfir::EntityWithAttributes{builder.create<hlfir::DeclareOp>(
loc, dest, "ctor.temp", /*shape=*/nullptr,
diff --git a/flang/test/Lower/HLFIR/charconvert.f90 b/flang/test/Lower/HLFIR/charconvert.f90
new file mode 100644
index 000000000000000..9779e79e4034d90
--- /dev/null
+++ b/flang/test/Lower/HLFIR/charconvert.f90
@@ -0,0 +1,60 @@
+! Test lowering of character concatenation to HLFIR
+! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s
+
+subroutine charconvert1(c,n)
+ character(*,4),intent(in) :: c(:)
+ integer,intent(in) :: n
+ interface
+ subroutine callee(c)
+ character(*),intent(in) :: c(:)
+ end subroutine callee
+ end interface
+ call show([character(n)::c])
+end subroutine charconvert1
+
+! CHECK-LABEL: func.func @_QPcharconvert1
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFcharconvert1Ec"} : (!fir.box<!fir.array<?x!fir.char<4,?>>>) -> (!fir.box<!fir.array<?x!fir.char<4,?>>>, !fir.box<!fir.array<?x!fir.char<4,?>>>)
+! CHECK: ^bb0(%[[ARG2:.*]]: index):
+! CHECK: %[[VAL_37:.*]] = fir.box_elesize %[[VAL_2]]#1 : (!fir.box<!fir.array<?x!fir.char<4,?>>>) -> index
+! CHECK: %[[C4_4:.*]] = arith.constant 4 : index
+! CHECK: %[[VAL_38:.*]] = arith.divsi %[[VAL_37]], %[[C4_4]] : index
+! CHECK: %[[VAL_39:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[ARG2]]) typeparams %[[VAL_38]] : (!fir.box<!fir.array<?x!fir.char<4,?>>>, index, index) -> !fir.boxchar<4>
+! CHECK: %[[C4_5:.*]] = arith.constant 4 : index
+! CHECK: %[[VAL_40:.*]] = arith.muli %[[VAL_38]], %[[C4_5]] : index
+! CHECK: %[[VAL_41:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_40]] : index)
+! CHECK: %[[VAL_42:.*]]:2 = fir.unboxchar %[[VAL_39]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index)
+! CHECK: fir.char_convert %[[VAL_42]]#0 for %[[VAL_38:.*]] to %[[VAL_41]] : !fir.ref<!fir.char<4,?>>, index, !fir.ref<!fir.char<1,?>>
+! CHECK: %[[VAL_43:.*]]:2 = hlfir.declare %[[VAL_41]] typeparams %[[VAL_38]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: hlfir.yield_element %[[VAL_43]]#0 : !fir.boxchar<1>
+! CHECK: }
+
+subroutine test2(x)
+ integer,intent(in) :: x
+ character(kind=4) :: cx
+ cx = achar(x)
+end subroutine test2
+! CHECK-LABEL: func.func @_QPtest2
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32>
+! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.char<1>
+! CHECK: %[[C1:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.char<4> {bindc_name = "cx", uniq_name = "_QFtest2Ecx"}
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[C1]] {uniq_name = "_QFtest2Ecx"} : (!fir.ref<!fir.char<4>>, index) -> (!fir.ref<!fir.char<4>>, !fir.ref<!fir.char<4>>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i64) -> i8
+! CHECK: %[[VAL_7:.*]] = fir.undefined !fir.char<1>
+! CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_6]], [0 : index] : (!fir.char<1>, i8) -> !fir.char<1>
+! CHECK: fir.store %[[VAL_8:.*]] to %[[VAL_0]] : !fir.ref<!fir.char<1>>
+! CHECK: %[[FALSE:.*]] = arith.constant false
+! CHECK: %[[VAL_9:.*]] = hlfir.as_expr %[[VAL_0]] move %[[FALSE]] : (!fir.ref<!fir.char<1>>, i1) -> !hlfir.expr<!fir.char<1>>
+! CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.char<4,?>(%[[C1_0]] : index)
+! CHECK: fir.char_convert %[[VAL_0:.*]] for %[[C1_0]] to %[[VAL_10]] : !fir.ref<!fir.char<1>>, index, !fir.ref<!fir.char<4,?>>
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] typeparams %[[C1_0]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.char<4,?>>, index) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>)
+! CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
+! CHECK: %[[VAL_12:.*]] = hlfir.set_length %[[VAL_11]]#0 len %[[C1_I64]] : (!fir.boxchar<4>, i64) -> !hlfir.expr<!fir.char<4>>
+! CHECK: hlfir.assign %[[VAL_12:.*]] to %[[VAL_2]]#0 : !hlfir.expr<!fir.char<4>>, !fir.ref<!fir.char<4>>
+! CHECK: hlfir.destroy %[[VAL_9:.*]] : !hlfir.expr<!fir.char<1>>
+! CHECK: return
+! CHECK: }
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on a fix!
4c4f233
to
94c1f85
Compare
186ae26
to
1f26ebf
Compare
1f26ebf
to
cb09b80
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing all the comments, LGTM
I messed up a push to the feature branch so I need to fix some stuff. I will make sure to fix this before closing and merging!!! |
cb09b80
to
d1ea5d2
Compare
d1ea5d2
to
07be72d
Compare
As shown in #64315, there were issues when trying to lower two flavors of Fortran code that implicitly perform
CHARACTER
conversion. Specifically, I address the following issues:@vzakhari @jeanPerier I borrowed a helper function from HLFIRTools.cpp. The function is
static
so I'm unable to link against it inflang/lib/Lower/ConvertExprToHLFIR.cpp
. Is there a cleaner way that what I've done, which is just copy/paste code?Thanks,
Anthony