Skip to content

Commit 4f2db80

Browse files
MattPDMatt P. Dziubinski
andauthored
[flang] Use alias analysis in lowering record assignments (llvm#176483)
Without alias analysis Flang assumes no aliasing in lowering record assignments which can result in miscompilation of programs using SEQUENCE types and EQUIVALENCE. Represent `SEQUENCE` in fir.type. For `SEQUENCE` types, use alias analysis to guard the fast path in `genRecordAssignment`; otherwise fall back to element-wise expansion. Update FIR FileCheck expectations Add `FIRAnalysis` to `"flang/unittests/Optimizer/CMakeLists.txt"` to fix the Windows x64 build failure (linker error). Fixes llvm#175246. Co-authored-by: Matt P. Dziubinski <matt-p.dziubinski@hpe.com>
1 parent 209ff8b commit 4f2db80

11 files changed

Lines changed: 354 additions & 262 deletions

File tree

flang/include/flang/Optimizer/Dialect/FIRTypes.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ def fir_RecordType : FIR_Type<"Record", "type"> {
357357
bool isPacked() const;
358358
void pack(bool);
359359

360+
// The presence of SEQUENCE attribute.
361+
bool isSequence() const;
362+
void setSequence(bool);
363+
360364
detail::RecordTypeStorage const *uniqueKey() const;
361365
}];
362366
}

flang/lib/Lower/ConvertType.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,12 @@ struct TypeBuilderImpl {
387387
return ty;
388388

389389
auto rec = fir::RecordType::get(context, converter.mangleName(tySpec));
390+
// Mark SEQUENCE derived types.
391+
if (const auto *details =
392+
typeSymbol.detailsIf<Fortran::semantics::DerivedTypeDetails>())
393+
if (details->sequence())
394+
rec.setSequence(true);
395+
390396
// Maintain the stack of types for recursive references and to speed-up
391397
// the derived type constructions that can be expensive for derived type
392398
// with dozens of components/parents (modern Fortran).

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "flang/Optimizer/Builder/FIRBuilder.h"
10+
#include "flang/Optimizer/Analysis/AliasAnalysis.h"
1011
#include "flang/Optimizer/Builder/BoxValue.h"
1112
#include "flang/Optimizer/Builder/Character.h"
1213
#include "flang/Optimizer/Builder/Complex.h"
@@ -1566,8 +1567,15 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
15661567
mlir::isa<fir::BaseBoxType>(fir::getBase(rhs).getType());
15671568
auto recTy = mlir::dyn_cast<fir::RecordType>(baseTy);
15681569
assert(recTy && "must be a record type");
1570+
1571+
// Use alias analysis to guard the fast path.
1572+
fir::AliasAnalysis aa;
1573+
// Aliased SEQUENCE types must take the conservative (slow) path.
1574+
bool disjoint = isTemporaryLHS || !recTy.isSequence() ||
1575+
(aa.alias(fir::getBase(lhs), fir::getBase(rhs)) ==
1576+
mlir::AliasResult::NoAlias);
15691577
if ((needFinalization && mayHaveFinalizer(recTy, builder)) ||
1570-
hasBoxOperands || !recordTypeCanBeMemCopied(recTy)) {
1578+
hasBoxOperands || !recordTypeCanBeMemCopied(recTy) || !disjoint) {
15711579
auto to = fir::getBase(builder.createBox(loc, lhs));
15721580
auto from = fir::getBase(builder.createBox(loc, rhs));
15731581
// The runtime entry point may modify the LHS descriptor if it is

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,21 @@ struct RecordTypeStorage : public mlir::TypeStorage {
183183

184184
bool isPacked() const { return packed; }
185185
void pack(bool p) { packed = p; }
186+
bool isSequence() const { return sequence; }
187+
void setSequence(bool s) { sequence = s; }
186188

187189
protected:
188190
std::string name;
189191
bool finalized;
190192
bool packed;
193+
bool sequence;
191194
std::vector<RecordType::TypePair> lens;
192195
std::vector<RecordType::TypePair> types;
193196

194197
private:
195198
RecordTypeStorage() = delete;
196199
explicit RecordTypeStorage(llvm::StringRef name)
197-
: name{name}, finalized{false}, packed{false} {}
200+
: name{name}, finalized{false}, packed{false}, sequence{false} {}
198201
};
199202

200203
} // namespace detail
@@ -1013,6 +1016,14 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
10131016
if (parser.parseLess() || parser.parseKeyword(&name))
10141017
return {};
10151018
RecordType result = RecordType::get(parser.getContext(), name);
1019+
// Optional SEQUENCE attribute: ", sequence"
1020+
if (!parser.parseOptionalComma()) {
1021+
if (parser.parseKeyword("sequence")) {
1022+
parser.emitError(parser.getNameLoc(), "expected 'sequence' keyword");
1023+
return {};
1024+
}
1025+
result.setSequence(true);
1026+
}
10161027

10171028
RecordType::TypeVector lenParamList;
10181029
if (!parser.parseOptionalLParen()) {
@@ -1068,6 +1079,8 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
10681079

10691080
void fir::RecordType::print(mlir::AsmPrinter &printer) const {
10701081
printer << "<" << getName();
1082+
if (isSequence())
1083+
printer << ",sequence";
10711084
if (!recordTypeVisited.count(uniqueKey())) {
10721085
recordTypeVisited.insert(uniqueKey());
10731086
if (getLenParamList().size()) {
@@ -1122,6 +1135,10 @@ void fir::RecordType::pack(bool p) { getImpl()->pack(p); }
11221135

11231136
bool fir::RecordType::isPacked() const { return getImpl()->isPacked(); }
11241137

1138+
bool fir::RecordType::isSequence() const { return getImpl()->isSequence(); }
1139+
1140+
void fir::RecordType::setSequence(bool s) { getImpl()->setSequence(s); }
1141+
11251142
detail::RecordTypeStorage const *fir::RecordType::uniqueKey() const {
11261143
return getImpl();
11271144
}

flang/test/Lower/HLFIR/cray-pointers.f90

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,25 +120,25 @@ subroutine test5()
120120
res = v(7)%i
121121
end subroutine test5
122122
! CHECK-LABEL: func.func @_QPtest5() {
123-
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>
123+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>
124124
! CHECK: %[[VAL_1:.*]] = fir.alloca i64 {bindc_name = "cp", uniq_name = "_QFtest5Ecp"}
125125
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<cray_pointer>, uniq_name = "_QFtest5Ecp"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>)
126126
! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index
127127
! CHECK: %[[VAL_6:.*]] = arith.constant 9 : index
128128
! CHECK: %[[VAL_8:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_6]] : (index, index) -> !fir.shapeshift<1>
129-
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer, cray_pointee>, uniq_name = "_QFtest5Ev"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>)
130-
! CHECK: %[[VAL_14:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>
131-
! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_14]](%[[VAL_8]]) : (!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>
132-
! CHECK: fir.store %[[VAL_15]] to %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>
129+
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer, cray_pointee>, uniq_name = "_QFtest5Ev"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>)
130+
! CHECK: %[[VAL_14:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>
131+
! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_14]](%[[VAL_8]]) : (!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>
132+
! CHECK: fir.store %[[VAL_15]] to %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>
133133
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>>
134134
! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.ptr<i64>>
135-
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_13]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>) -> !fir.ref<!fir.box<none>>
135+
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_13]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>) -> !fir.ref<!fir.box<none>>
136136
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.ptr<i64>) -> !fir.llvm_ptr<i8>
137137
! CHECK: fir.call @_FortranAPointerAssociateScalar(%[[VAL_18]], %[[VAL_19]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.llvm_ptr<i8>) -> ()
138-
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>
138+
! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>
139139
! CHECK: %[[VAL_22:.*]] = arith.constant 7 : index
140-
! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_21]] (%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>, index) -> !fir.ref<!fir.type<_QFtest5Tt{r:f32,i:i32}>>
141-
! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_23]]{"i"} : (!fir.ref<!fir.type<_QFtest5Tt{r:f32,i:i32}>>) -> !fir.ref<i32>
140+
! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_21]] (%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>, index) -> !fir.ref<!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>
141+
! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_23]]{"i"} : (!fir.ref<!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>) -> !fir.ref<i32>
142142
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<i32>
143143

144144
subroutine test6(n)

0 commit comments

Comments
 (0)