Skip to content

Commit a86283a

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:e00f2272d640 into amd-gfx:7a55dcafa40e
Local branch amd-gfx 7a55dca Merged main:9f406e450b6d into amd-gfx:7e7cb7e72c63 Remote branch main e00f227 [lldb][FreeBSD] fix i386 size_t error when using LLDB_LOGF (llvm#68210)
2 parents 7a55dca + e00f227 commit a86283a

File tree

19 files changed

+1030
-922
lines changed

19 files changed

+1030
-922
lines changed

clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class HTMLLogger : public Logger {
150150
const CFGBlock *Block;
151151
unsigned Iter;
152152
bool PostVisit;
153+
bool Converged;
153154
};
154155

155156
StreamFactory Streams;
@@ -159,8 +160,8 @@ class HTMLLogger : public Logger {
159160
const ControlFlowContext *CFG;
160161
// Timeline of iterations of CFG block visitation.
161162
std::vector<Iteration> Iters;
162-
// Number of times each CFG block has been seen.
163-
llvm::DenseMap<const CFGBlock *, llvm::SmallVector<Iteration>> BlockIters;
163+
// Indexes in `Iters` of the iterations for each block.
164+
llvm::DenseMap<const CFGBlock *, llvm::SmallVector<size_t>> BlockIters;
164165
// The messages logged in the current context but not yet written.
165166
std::string ContextLogs;
166167
// The number of elements we have visited within the current CFG block.
@@ -207,6 +208,7 @@ class HTMLLogger : public Logger {
207208
JOS->attribute("block", blockID(E.Block->getBlockID()));
208209
JOS->attribute("iter", E.Iter);
209210
JOS->attribute("post_visit", E.PostVisit);
211+
JOS->attribute("converged", E.Converged);
210212
});
211213
}
212214
});
@@ -222,10 +224,10 @@ class HTMLLogger : public Logger {
222224
}
223225

224226
void enterBlock(const CFGBlock &B, bool PostVisit) override {
225-
llvm::SmallVector<Iteration> &BIter = BlockIters[&B];
227+
llvm::SmallVector<size_t> &BIter = BlockIters[&B];
226228
unsigned IterNum = BIter.size() + 1;
227-
BIter.push_back({&B, IterNum, PostVisit});
228-
Iters.push_back({&B, IterNum, PostVisit});
229+
BIter.push_back(Iters.size());
230+
Iters.push_back({&B, IterNum, PostVisit, /*Converged=*/false});
229231
ElementIndex = 0;
230232
}
231233
void enterElement(const CFGElement &E) override {
@@ -290,7 +292,7 @@ class HTMLLogger : public Logger {
290292
}
291293
});
292294
}
293-
void blockConverged() override { logText("Block converged"); }
295+
void blockConverged() override { Iters.back().Converged = true; }
294296

295297
void logText(llvm::StringRef S) override {
296298
ContextLogs.append(S.begin(), S.end());
@@ -301,13 +303,15 @@ class HTMLLogger : public Logger {
301303
// Write the CFG block details.
302304
// Currently this is just the list of elements in execution order.
303305
// FIXME: an AST dump would be a useful view, too.
304-
void writeBlock(const CFGBlock &B, llvm::ArrayRef<Iteration> ItersForB) {
306+
void writeBlock(const CFGBlock &B, llvm::ArrayRef<size_t> ItersForB) {
305307
JOS->attributeObject(blockID(B.getBlockID()), [&] {
306308
JOS->attributeArray("iters", [&] {
307-
for (const auto &Iter : ItersForB) {
309+
for (size_t IterIdx : ItersForB) {
310+
const Iteration &Iter = Iters[IterIdx];
308311
JOS->object([&] {
309312
JOS->attribute("iter", Iter.Iter);
310313
JOS->attribute("post_visit", Iter.PostVisit);
314+
JOS->attribute("converged", Iter.Converged);
311315
});
312316
}
313317
});

clang/lib/Analysis/FlowSensitive/HTMLLogger.html

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
{{entry.block}}
4646
<template data-if="entry.post_visit">(post-visit)</template>
4747
<template data-if="!entry.post_visit">({{entry.iter}})</template>
48+
<template data-if="entry.converged"> &#x2192;&#x7c;<!--Rightwards arrow, vertical line--></template>
4849
</div>
4950
</template>
5051
</section>
@@ -62,6 +63,7 @@
6263
<a class="chooser {{selection.bb}}:{{iter.iter}}" data-iter="{{selection.bb}}:{{iter.iter}}">
6364
<template data-if="iter.post_visit">Post-visit</template>
6465
<template data-if="!iter.post_visit">Iteration {{iter.iter}}</template>
66+
<template data-if="iter.converged"> &#x2192;&#x7c;<!--Rightwards arrow, vertical line--></template>
6567
</a>
6668
</template>
6769
</div>

compiler-rt/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
cmake_minimum_required(VERSION 3.20.0)
77

8-
set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
8+
if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS)
9+
set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
10+
endif()
911
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
1012
NO_POLICY_SCOPE)
1113

flang/include/flang/Lower/HlfirIntrinsics.h

+64-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#define FORTRAN_LOWER_HLFIRINTRINSICS_H
2020

2121
#include "flang/Optimizer/Builder/HLFIRTools.h"
22+
#include "flang/Optimizer/Builder/Todo.h"
23+
#include "flang/Optimizer/HLFIR/HLFIROps.h"
2224
#include "llvm/ADT/SmallVector.h"
2325
#include <cassert>
2426
#include <optional>
@@ -46,18 +48,71 @@ struct PreparedActualArgument {
4648
PreparedActualArgument(hlfir::Entity actual,
4749
std::optional<mlir::Value> isPresent)
4850
: actual{actual}, isPresent{isPresent} {}
51+
PreparedActualArgument(hlfir::ElementalAddrOp vectorSubscriptedActual)
52+
: actual{vectorSubscriptedActual}, isPresent{std::nullopt} {}
4953
void setElementalIndices(mlir::ValueRange &indices) {
5054
oneBasedElementalIndices = &indices;
5155
}
52-
hlfir::Entity getActual(mlir::Location loc,
53-
fir::FirOpBuilder &builder) const {
54-
if (oneBasedElementalIndices)
55-
return hlfir::getElementAt(loc, builder, actual,
56-
*oneBasedElementalIndices);
57-
return actual;
56+
57+
/// Get the prepared actual. If this is an array argument in an elemental
58+
/// call, the current element value will be returned.
59+
hlfir::Entity getActual(mlir::Location loc, fir::FirOpBuilder &builder) const;
60+
61+
void derefPointersAndAllocatables(mlir::Location loc,
62+
fir::FirOpBuilder &builder) {
63+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual))
64+
actual = hlfir::derefPointersAndAllocatables(loc, builder, *actualEntity);
65+
}
66+
67+
void loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder) {
68+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual))
69+
actual = hlfir::loadTrivialScalar(loc, builder, *actualEntity);
70+
}
71+
72+
/// Ensure an array expression argument is fully evaluated in memory before
73+
/// the call. Useful for impure elemental calls.
74+
hlfir::AssociateOp associateIfArrayExpr(mlir::Location loc,
75+
fir::FirOpBuilder &builder) {
76+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) {
77+
if (!actualEntity->isVariable() && actualEntity->isArray()) {
78+
mlir::Type storageType = actualEntity->getType();
79+
hlfir::AssociateOp associate = hlfir::genAssociateExpr(
80+
loc, builder, *actualEntity, storageType, "adapt.impure_arg_eval");
81+
actual = hlfir::Entity{associate};
82+
return associate;
83+
}
84+
}
85+
return {};
86+
}
87+
88+
bool isArray() const {
89+
return std::holds_alternative<hlfir::ElementalAddrOp>(actual) ||
90+
std::get<hlfir::Entity>(actual).isArray();
5891
}
59-
hlfir::Entity getOriginalActual() const { return actual; }
60-
void setOriginalActual(hlfir::Entity newActual) { actual = newActual; }
92+
93+
mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder) {
94+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual))
95+
return hlfir::genShape(loc, builder, *actualEntity);
96+
return std::get<hlfir::ElementalAddrOp>(actual).getShape();
97+
}
98+
99+
mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder) {
100+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual))
101+
return hlfir::genCharLength(loc, builder, *actualEntity);
102+
auto typeParams = std::get<hlfir::ElementalAddrOp>(actual).getTypeparams();
103+
assert(typeParams.size() == 1 &&
104+
"failed to retrieve vector subscripted character length");
105+
return typeParams[0];
106+
}
107+
108+
/// When the argument is polymorphic, get mold value with the same dynamic
109+
/// type.
110+
mlir::Value getPolymorphicMold(mlir::Location loc) const {
111+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual))
112+
return *actualEntity;
113+
TODO(loc, "polymorphic vector subscripts");
114+
}
115+
61116
bool handleDynamicOptional() const { return isPresent.has_value(); }
62117
mlir::Value getIsPresent() const {
63118
assert(handleDynamicOptional() && "not a dynamic optional");
@@ -67,7 +122,7 @@ struct PreparedActualArgument {
67122
void resetOptionalAspect() { isPresent = std::nullopt; }
68123

69124
private:
70-
hlfir::Entity actual;
125+
std::variant<hlfir::Entity, hlfir::ElementalAddrOp> actual;
71126
mlir::ValueRange *oneBasedElementalIndices{nullptr};
72127
// When the actual may be dynamically optional, "isPresent"
73128
// holds a boolean value indicating the presence of the

flang/lib/Lower/ConvertCall.cpp

+50-24
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "flang/Optimizer/Builder/Todo.h"
3030
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
3131
#include "flang/Optimizer/HLFIR/HLFIROps.h"
32+
#include "mlir/IR/IRMapping.h"
3233
#include "llvm/Support/CommandLine.h"
3334
#include "llvm/Support/Debug.h"
3435
#include <optional>
@@ -1619,37 +1620,33 @@ class ElementalCallBuilder {
16191620
for (unsigned i = 0; i < numArgs; ++i) {
16201621
auto &preparedActual = loweredActuals[i];
16211622
if (preparedActual) {
1622-
hlfir::Entity actual = preparedActual->getOriginalActual();
16231623
// Elemental procedure dummy arguments cannot be pointer/allocatables
16241624
// (C15100), so it is safe to dereference any pointer or allocatable
16251625
// actual argument now instead of doing this inside the elemental
16261626
// region.
1627-
actual = hlfir::derefPointersAndAllocatables(loc, builder, actual);
1627+
preparedActual->derefPointersAndAllocatables(loc, builder);
16281628
// Better to load scalars outside of the loop when possible.
16291629
if (!preparedActual->handleDynamicOptional() &&
16301630
impl().canLoadActualArgumentBeforeLoop(i))
1631-
actual = hlfir::loadTrivialScalar(loc, builder, actual);
1631+
preparedActual->loadTrivialScalar(loc, builder);
16321632
// TODO: merge shape instead of using the first one.
1633-
if (!shape && actual.isArray()) {
1633+
if (!shape && preparedActual->isArray()) {
16341634
if (preparedActual->handleDynamicOptional())
16351635
optionalWithShape = &*preparedActual;
16361636
else
1637-
shape = hlfir::genShape(loc, builder, actual);
1637+
shape = preparedActual->genShape(loc, builder);
16381638
}
16391639
// 15.8.3 p1. Elemental procedure with intent(out)/intent(inout)
16401640
// arguments must be called in element order.
16411641
if (impl().argMayBeModifiedByCall(i))
16421642
mustBeOrdered = true;
1643-
// Propagates pointer dereferences and scalar loads.
1644-
preparedActual->setOriginalActual(actual);
16451643
}
16461644
}
16471645
if (!shape && optionalWithShape) {
16481646
// If all array operands appear in optional positions, then none of them
16491647
// is allowed to be absent as per 15.5.2.12 point 3. (6). Just pick the
16501648
// first operand.
1651-
shape =
1652-
hlfir::genShape(loc, builder, optionalWithShape->getOriginalActual());
1649+
shape = optionalWithShape->genShape(loc, builder);
16531650
// TODO: There is an opportunity to add a runtime check here that
16541651
// this array is present as required. Also, the optionality of all actual
16551652
// could be checked and reset given the Fortran requirement.
@@ -1663,16 +1660,10 @@ class ElementalCallBuilder {
16631660
// intent(inout) arguments. Note that the scalar arguments are handled
16641661
// above.
16651662
if (mustBeOrdered) {
1666-
for (unsigned i = 0; i < numArgs; ++i) {
1667-
auto &preparedActual = loweredActuals[i];
1663+
for (auto &preparedActual : loweredActuals) {
16681664
if (preparedActual) {
1669-
hlfir::Entity actual = preparedActual->getOriginalActual();
1670-
if (!actual.isVariable() && actual.isArray()) {
1671-
mlir::Type storageType = actual.getType();
1672-
hlfir::AssociateOp associate = hlfir::genAssociateExpr(
1673-
loc, builder, actual, storageType, "adapt.impure_arg_eval");
1674-
preparedActual->setOriginalActual(hlfir::Entity{associate});
1675-
1665+
if (hlfir::AssociateOp associate =
1666+
preparedActual->associateIfArrayExpr(loc, builder)) {
16761667
fir::FirOpBuilder *bldr = &builder;
16771668
callContext.stmtCtx.attachCleanup(
16781669
[=]() { bldr->create<hlfir::EndAssociateOp>(loc, associate); });
@@ -1852,9 +1843,8 @@ class ElementalIntrinsicCallBuilder
18521843
if (intrinsic)
18531844
if (intrinsic->name == "adjustr" || intrinsic->name == "adjustl" ||
18541845
intrinsic->name == "merge")
1855-
return hlfir::genCharLength(
1856-
callContext.loc, callContext.getBuilder(),
1857-
loweredActuals[0].value().getOriginalActual());
1846+
return loweredActuals[0].value().genCharLength(
1847+
callContext.loc, callContext.getBuilder());
18581848
// Character MIN/MAX is the min/max of the arguments length that are
18591849
// present.
18601850
TODO(callContext.loc,
@@ -1874,7 +1864,7 @@ class ElementalIntrinsicCallBuilder
18741864
// the same declared and dynamic types. So any of them can be used
18751865
// for the mold.
18761866
assert(!loweredActuals.empty());
1877-
return loweredActuals.front()->getOriginalActual();
1867+
return loweredActuals.front()->getPolymorphicMold(callContext.loc);
18781868
}
18791869

18801870
return {};
@@ -2137,7 +2127,7 @@ genProcedureRef(CallContext &callContext) {
21372127
Fortran::lower::CallerInterface caller(callContext.procRef,
21382128
callContext.converter);
21392129
mlir::FunctionType callSiteType = caller.genFunctionType();
2140-
2130+
const bool isElemental = callContext.isElementalProcWithArrayArgs();
21412131
Fortran::lower::PreparedActualArguments loweredActuals;
21422132
// Lower the actual arguments
21432133
for (const Fortran::lower::CallInterface<
@@ -2162,6 +2152,21 @@ genProcedureRef(CallContext &callContext) {
21622152
}
21632153
}
21642154

2155+
if (isElemental && !arg.hasValueAttribute() &&
2156+
Fortran::evaluate::IsVariable(*expr) &&
2157+
Fortran::evaluate::HasVectorSubscript(*expr)) {
2158+
// Vector subscripted arguments are copied in calls, except in elemental
2159+
// calls without VALUE attribute where Fortran 2018 15.5.2.4 point 21
2160+
// does not apply and the address of each element must be passed.
2161+
hlfir::ElementalAddrOp elementalAddr =
2162+
Fortran::lower::convertVectorSubscriptedExprToElementalAddr(
2163+
loc, callContext.converter, *expr, callContext.symMap,
2164+
callContext.stmtCtx);
2165+
loweredActuals.emplace_back(
2166+
Fortran::lower::PreparedActualArgument{elementalAddr});
2167+
continue;
2168+
}
2169+
21652170
auto loweredActual = Fortran::lower::convertExprToHLFIR(
21662171
loc, callContext.converter, *expr, callContext.symMap,
21672172
callContext.stmtCtx);
@@ -2178,7 +2183,7 @@ genProcedureRef(CallContext &callContext) {
21782183
// Optional dummy argument for which there is no actual argument.
21792184
loweredActuals.emplace_back(std::nullopt);
21802185
}
2181-
if (callContext.isElementalProcWithArrayArgs()) {
2186+
if (isElemental) {
21822187
bool isImpure = false;
21832188
if (const Fortran::semantics::Symbol *procSym =
21842189
callContext.procRef.proc().GetSymbol())
@@ -2189,6 +2194,27 @@ genProcedureRef(CallContext &callContext) {
21892194
return genUserCall(loweredActuals, caller, callSiteType, callContext);
21902195
}
21912196

2197+
hlfir::Entity Fortran::lower::PreparedActualArgument::getActual(
2198+
mlir::Location loc, fir::FirOpBuilder &builder) const {
2199+
if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) {
2200+
if (oneBasedElementalIndices)
2201+
return hlfir::getElementAt(loc, builder, *actualEntity,
2202+
*oneBasedElementalIndices);
2203+
return *actualEntity;
2204+
}
2205+
assert(oneBasedElementalIndices && "expect elemental context");
2206+
hlfir::ElementalAddrOp elementalAddr =
2207+
std::get<hlfir::ElementalAddrOp>(actual);
2208+
mlir::IRMapping mapper;
2209+
auto alwaysFalse = [](hlfir::ElementalOp) -> bool { return false; };
2210+
mlir::Value addr = hlfir::inlineElementalOp(
2211+
loc, builder, elementalAddr, *oneBasedElementalIndices, mapper,
2212+
/*mustRecursivelyInline=*/alwaysFalse);
2213+
assert(elementalAddr.getCleanup().empty() && "no clean-up expected");
2214+
elementalAddr.erase();
2215+
return hlfir::Entity{addr};
2216+
}
2217+
21922218
bool Fortran::lower::isIntrinsicModuleProcRef(
21932219
const Fortran::evaluate::ProcedureRef &procRef) {
21942220
const Fortran::semantics::Symbol *symbol = procRef.proc().GetSymbol();

flang/lib/Lower/HlfirIntrinsics.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ mlir::Value HlfirTransformationalIntrinsic::loadBoxAddress(
152152
if (!arg)
153153
return mlir::Value{};
154154

155-
hlfir::Entity actual = arg->getOriginalActual();
155+
hlfir::Entity actual = arg->getActual(loc, builder);
156156

157157
if (!arg->handleDynamicOptional()) {
158158
if (actual.isMutableBox()) {
@@ -193,7 +193,7 @@ llvm::SmallVector<mlir::Value> HlfirTransformationalIntrinsic::getOperandVector(
193193
operands.emplace_back();
194194
continue;
195195
}
196-
hlfir::Entity actual = arg->getOriginalActual();
196+
hlfir::Entity actual = arg->getActual(loc, builder);
197197
mlir::Value valArg;
198198

199199
if (!argLowering) {

0 commit comments

Comments
 (0)