4 changes: 4 additions & 0 deletions clang/test/Driver/aarch64-mcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
// CORTEX-A715: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a715"
// RUN: %clang --target=aarch64 -mcpu=cortex-a720 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720 %s
// CORTEX-A720: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720"
// RUN: %clang --target=aarch64 -mcpu=cortex-a720ae -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720AE %s
// CORTEX-A720AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720ae"
// RUN: %clang --target=aarch64 -mcpu=neoverse-e1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-E1 %s
// NEOVERSE-E1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-e1"
// RUN: %clang --target=aarch64 -mcpu=neoverse-v1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-V1 %s
Expand All @@ -70,6 +72,8 @@
// NEOVERSE-512TVB: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-512tvb"
// RUN: %clang --target=aarch64 -mcpu=cortex-a520 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A520 %s
// CORTEX-A520: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a520"
// RUN: %clang --target=aarch64 -mcpu=cortex-a520ae -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A520AE %s
// CORTEX-A520AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a520ae"

// RUN: %clang --target=aarch64 -mcpu=cortex-r82 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXR82 %s
// CORTEXR82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-r82"
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Misc/target-invalid-cpu-note.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

// RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
// AARCH64: error: unknown target CPU 'not-a-cpu'
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64
// TUNE_AARCH64: error: unknown target CPU 'not-a-cpu'
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
// X86: error: unknown target CPU 'not-a-cpu'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3383,6 +3383,66 @@ TEST_P(UncheckedOptionalAccessTest, LambdaCaptureStateNotPropagated) {
}
)");
}

TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptional) {
ExpectDiagnosticsFor(R"(
#include "unchecked_optional_access_test.h"
struct Derived : public $ns::$optional<int> {};
void target(Derived opt) {
*opt; // [[unsafe]]
if (opt.has_value())
*opt;
// The same thing, but with a pointer receiver.
Derived *popt = &opt;
**popt; // [[unsafe]]
if (popt->has_value())
**popt;
}
)");
}

TEST_P(UncheckedOptionalAccessTest, ClassTemplateDerivedFromOptional) {
ExpectDiagnosticsFor(R"(
#include "unchecked_optional_access_test.h"
template <class T>
struct Derived : public $ns::$optional<T> {};
void target(Derived<int> opt) {
*opt; // [[unsafe]]
if (opt.has_value())
*opt;
// The same thing, but with a pointer receiver.
Derived<int> *popt = &opt;
**popt; // [[unsafe]]
if (popt->has_value())
**popt;
}
)");
}

TEST_P(UncheckedOptionalAccessTest, ClassDerivedPrivatelyFromOptional) {
// Classes that derive privately from optional can themselves still call
// member functions of optional. Check that we model the optional correctly
// in this situation.
ExpectDiagnosticsFor(R"(
#include "unchecked_optional_access_test.h"
struct Derived : private $ns::$optional<int> {
void Method() {
**this; // [[unsafe]]
if (this->has_value())
**this;
}
};
)",
ast_matchers::hasName("Method"));
}

// FIXME: Add support for:
// - constructors (copy, move)
// - assignment operators (default, copy, move)
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/test/tsan/signal_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int main() {

struct sigaction act = {};
act.sa_handler = &handler;
if (sigaction(SIGALRM, &act, 0)) {
if (sigaction(SIGVTALRM, &act, 0)) {
perror("sigaction");
exit(1);
}
Expand All @@ -39,7 +39,7 @@ int main() {
t.it_value.tv_sec = 0;
t.it_value.tv_usec = 10;
t.it_interval = t.it_value;
if (setitimer(ITIMER_REAL, &t, 0)) {
if (setitimer(ITIMER_VIRTUAL, &t, 0)) {
perror("setitimer");
exit(1);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/test/tsan/signal_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static void* thr(void *p) {
int main() {
struct sigaction act = {};
act.sa_handler = &handler;
if (sigaction(SIGALRM, &act, 0)) {
if (sigaction(SIGVTALRM, &act, 0)) {
perror("sigaction");
exit(1);
}
Expand All @@ -33,7 +33,7 @@ int main() {
t.it_value.tv_sec = 0;
t.it_value.tv_usec = 10;
t.it_interval = t.it_value;
if (setitimer(ITIMER_REAL, &t, 0)) {
if (setitimer(ITIMER_VIRTUAL, &t, 0)) {
perror("setitimer");
exit(1);
}
Expand Down
8 changes: 8 additions & 0 deletions flang/include/flang/Evaluate/characteristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ class TypeAndShape {
int corank() const { return corank_; }

int Rank() const { return GetRank(shape_); }

// Can sequence association apply to this argument?
bool CanBeSequenceAssociated() const {
constexpr Attrs notAssumedOrExplicitShape{
~Attrs{Attr::AssumedSize, Attr::Coarray}};
return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none();
}

bool IsCompatibleWith(parser::ContextualMessages &, const TypeAndShape &that,
const char *thisIs = "pointer", const char *thatIs = "target",
bool omitShapeConformanceCheck = false,
Expand Down
40 changes: 35 additions & 5 deletions flang/include/flang/Lower/CallInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ class CallInterface {
/// May the dummy argument require INTENT(OUT) finalization
/// on entry to the invoked procedure? Provides conservative answer.
bool mayRequireIntentoutFinalization() const;
/// Is the dummy argument an explicit-shape or assumed-size array that
/// must be passed by descriptor? Sequence association imply the actual
/// argument shape/rank may differ with the dummy shape/rank (see F'2023
/// section 15.5.2.12), so care is needed when creating the descriptor
/// for the dummy argument.
bool isSequenceAssociatedDescriptor() const;
/// How entity is passed by.
PassEntityBy passBy;
/// What is the entity (SymbolRef for callee/ActualArgument* for caller)
Expand Down Expand Up @@ -273,8 +279,6 @@ class CallerInterface : public CallInterface<CallerInterface> {
actualInputs.resize(getNumFIRArguments());
}

using ExprVisitor = std::function<void(evaluate::Expr<evaluate::SomeType>)>;

/// CRTP callbacks
bool hasAlternateReturns() const;
std::string getMangledName() const;
Expand Down Expand Up @@ -312,12 +316,21 @@ class CallerInterface : public CallInterface<CallerInterface> {
/// procedure.
const Fortran::semantics::Symbol *getProcedureSymbol() const;

/// Return the dummy argument symbol if this is a call to a user
/// defined procedure with explicit interface. Returns nullptr if there
/// is no user defined explicit interface.
const Fortran::semantics::Symbol *
getDummySymbol(const PassedEntity &entity) const;

/// Helpers to place the lowered arguments at the right place once they
/// have been lowered.
void placeInput(const PassedEntity &passedEntity, mlir::Value arg);
void placeAddressAndLengthInput(const PassedEntity &passedEntity,
mlir::Value addr, mlir::Value len);

/// Get lowered FIR argument given the Fortran argument.
mlir::Value getInput(const PassedEntity &passedEntity);

/// If this is a call to a procedure pointer or dummy, returns the related
/// procedure designator. Nullptr otherwise.
const Fortran::evaluate::ProcedureDesignator *getIfIndirectCall() const;
Expand All @@ -333,13 +346,27 @@ class CallerInterface : public CallInterface<CallerInterface> {
/// the result specification expressions (extents and lengths) ? If needed,
/// this mapping must be done after argument lowering, and before the call
/// itself.
bool mustMapInterfaceSymbols() const;
bool mustMapInterfaceSymbolsForResult() const;
/// Must the caller map function interface symbols in order to evaluate
/// the specification expressions of a given dummy argument?
bool mustMapInterfaceSymbolsForDummyArgument(const PassedEntity &) const;

/// Visitor for specification expression. Boolean indicate the specification
/// expression is for the last extent of an assumed size array.
using ExprVisitor =
std::function<void(evaluate::Expr<evaluate::SomeType>, bool)>;

/// Walk the result non-deferred extent specification expressions.
void walkResultExtents(ExprVisitor) const;
void walkResultExtents(const ExprVisitor &) const;

/// Walk the result non-deferred length specification expressions.
void walkResultLengths(ExprVisitor) const;
void walkResultLengths(const ExprVisitor &) const;
/// Walk non-deferred extent specification expressions of a dummy argument.
void walkDummyArgumentExtents(const PassedEntity &,
const ExprVisitor &) const;
/// Walk non-deferred length specification expressions of a dummy argument.
void walkDummyArgumentLengths(const PassedEntity &,
const ExprVisitor &) const;

/// Get the mlir::Value that is passed as argument \p sym of the function
/// being called. The arguments must have been placed before calling this
Expand All @@ -355,6 +382,9 @@ class CallerInterface : public CallInterface<CallerInterface> {
/// returns the storage type.
mlir::Type getResultStorageType() const;

/// Return FIR type of argument.
mlir::Type getDummyArgumentType(const PassedEntity &) const;

// Copy of base implementation.
static constexpr bool hasHostAssociated() { return false; }
mlir::Type getHostAssociatedTy() const {
Expand Down
13 changes: 10 additions & 3 deletions flang/include/flang/Lower/ConvertVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,16 @@ void mapSymbolAttributes(AbstractConverter &, const semantics::SymbolRef &,
/// Instantiate the variables that appear in the specification expressions
/// of the result of a function call. The instantiated variables are added
/// to \p symMap.
void mapCallInterfaceSymbols(AbstractConverter &,
const Fortran::lower::CallerInterface &caller,
SymMap &symMap);
void mapCallInterfaceSymbolsForResult(
AbstractConverter &, const Fortran::lower::CallerInterface &caller,
SymMap &symMap);

/// Instantiate the variables that appear in the specification expressions
/// of a dummy argument of a procedure call. The instantiated variables are
/// added to \p symMap.
void mapCallInterfaceSymbolsForDummyArgument(
AbstractConverter &, const Fortran::lower::CallerInterface &caller,
SymMap &symMap, const Fortran::semantics::Symbol &dummySymbol);

// TODO: consider saving the initial expression symbol dependence analysis in
// in the PFT variable and dealing with the dependent symbols instantiation in
Expand Down
3 changes: 0 additions & 3 deletions flang/include/flang/Lower/LoweringOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ LOWERINGOPT(Name, Bits, Default)
/// If true, lower transpose without a runtime call.
ENUM_LOWERINGOPT(OptimizeTranspose, unsigned, 1, 1)

/// If true, enable polymorphic type lowering feature. On by default.
ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 1)

/// If true, lower to High level FIR before lowering to FIR. On by default.
ENUM_LOWERINGOPT(LowerToHighLevelFIR, unsigned, 1, 1)

Expand Down
392 changes: 210 additions & 182 deletions flang/include/flang/Semantics/openmp-directive-sets.h

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,6 @@ bool CompilerInvocation::createFromArgs(
invoc.loweringOpts.setLowerToHighLevelFIR(false);
}

if (args.hasArg(
clang::driver::options::OPT_flang_experimental_polymorphism)) {
invoc.loweringOpts.setPolymorphicTypeImpl(true);
}

// -fno-ppc-native-vector-element-order
if (args.hasArg(clang::driver::options::OPT_fno_ppc_native_vec_elem_order)) {
invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
Expand Down
140 changes: 110 additions & 30 deletions flang/lib/Lower/CallInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,21 +310,22 @@ bool Fortran::lower::CallerInterface::verifyActualInputs() const {
return true;
}

void Fortran::lower::CallerInterface::walkResultLengths(
ExprVisitor visitor) const {
assert(characteristic && "characteristic was not computed");
const Fortran::evaluate::characteristics::FunctionResult &result =
characteristic->functionResult.value();
const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape =
result.GetTypeAndShape();
assert(typeAndShape && "no result type");
Fortran::evaluate::DynamicType dynamicType = typeAndShape->type();
// Visit result length specification expressions that are explicit.
mlir::Value
Fortran::lower::CallerInterface::getInput(const PassedEntity &passedEntity) {
return actualInputs[passedEntity.firArgument];
}

static void walkLengths(
const Fortran::evaluate::characteristics::TypeAndShape &typeAndShape,
const Fortran::lower::CallerInterface::ExprVisitor &visitor,
Fortran::lower::AbstractConverter &converter) {
Fortran::evaluate::DynamicType dynamicType = typeAndShape.type();
// Visit length specification expressions that are explicit.
if (dynamicType.category() == Fortran::common::TypeCategory::Character) {
if (std::optional<Fortran::evaluate::ExtentExpr> length =
dynamicType.GetCharLength())
visitor(toEvExpr(*length));
} else if (dynamicType.category() == common::TypeCategory::Derived &&
visitor(toEvExpr(*length), /*assumedSize=*/false);
} else if (dynamicType.category() == Fortran::common::TypeCategory::Derived &&
!dynamicType.IsUnlimitedPolymorphic()) {
const Fortran::semantics::DerivedTypeSpec &derivedTypeSpec =
dynamicType.GetDerivedTypeSpec();
Expand All @@ -334,32 +335,61 @@ void Fortran::lower::CallerInterface::walkResultLengths(
}
}

void Fortran::lower::CallerInterface::walkResultLengths(
const ExprVisitor &visitor) const {
assert(characteristic && "characteristic was not computed");
const Fortran::evaluate::characteristics::FunctionResult &result =
characteristic->functionResult.value();
const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape =
result.GetTypeAndShape();
assert(typeAndShape && "no result type");
return walkLengths(*typeAndShape, visitor, converter);
}

void Fortran::lower::CallerInterface::walkDummyArgumentLengths(
const PassedEntity &passedEntity, const ExprVisitor &visitor) const {
if (!passedEntity.characteristics)
return;
if (const auto *dummy =
std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
&passedEntity.characteristics->u))
walkLengths(dummy->type, visitor, converter);
}

// Compute extent expr from shapeSpec of an explicit shape.
// TODO: Allow evaluate shape analysis to work in a mode where it disregards
// the non-constant aspects when building the shape to avoid having this here.
static Fortran::evaluate::ExtentExpr
getExtentExpr(const Fortran::semantics::ShapeSpec &shapeSpec) {
if (shapeSpec.ubound().isStar())
// F'2023 18.5.3 point 5.
return Fortran::evaluate::ExtentExpr{-1};
const auto &ubound = shapeSpec.ubound().GetExplicit();
const auto &lbound = shapeSpec.lbound().GetExplicit();
assert(lbound && ubound && "shape must be explicit");
return Fortran::common::Clone(*ubound) - Fortran::common::Clone(*lbound) +
Fortran::evaluate::ExtentExpr{1};
}

static void
walkExtents(const Fortran::semantics::Symbol &symbol,
const Fortran::lower::CallerInterface::ExprVisitor &visitor) {
if (const auto *objectDetails =
symbol.detailsIf<Fortran::semantics::ObjectEntityDetails>())
if (objectDetails->shape().IsExplicitShape() ||
Fortran::semantics::IsAssumedSizeArray(symbol))
for (const Fortran::semantics::ShapeSpec &shapeSpec :
objectDetails->shape())
visitor(Fortran::evaluate::AsGenericExpr(getExtentExpr(shapeSpec)),
/*assumedSize=*/shapeSpec.ubound().isStar());
}

void Fortran::lower::CallerInterface::walkResultExtents(
ExprVisitor visitor) const {
const ExprVisitor &visitor) const {
// Walk directly the result symbol shape (the characteristic shape may contain
// descriptor inquiries to it that would fail to lower on the caller side).
const Fortran::semantics::SubprogramDetails *interfaceDetails =
getInterfaceDetails();
if (interfaceDetails) {
const Fortran::semantics::Symbol &result = interfaceDetails->result();
if (const auto *objectDetails =
result.detailsIf<Fortran::semantics::ObjectEntityDetails>())
if (objectDetails->shape().IsExplicitShape())
for (const Fortran::semantics::ShapeSpec &shapeSpec :
objectDetails->shape())
visitor(Fortran::evaluate::AsGenericExpr(getExtentExpr(shapeSpec)));
walkExtents(interfaceDetails->result(), visitor);
} else {
if (procRef.Rank() != 0)
fir::emitFatalError(
Expand All @@ -368,22 +398,44 @@ void Fortran::lower::CallerInterface::walkResultExtents(
}
}

bool Fortran::lower::CallerInterface::mustMapInterfaceSymbols() const {
void Fortran::lower::CallerInterface::walkDummyArgumentExtents(
const PassedEntity &passedEntity, const ExprVisitor &visitor) const {
const Fortran::semantics::SubprogramDetails *interfaceDetails =
getInterfaceDetails();
if (!interfaceDetails)
return;
const Fortran::semantics::Symbol *dummy = getDummySymbol(passedEntity);
assert(dummy && "dummy symbol was not set");
walkExtents(*dummy, visitor);
}

bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForResult() const {
assert(characteristic && "characteristic was not computed");
const std::optional<Fortran::evaluate::characteristics::FunctionResult>
&result = characteristic->functionResult;
if (!result || result->CanBeReturnedViaImplicitInterface() ||
!getInterfaceDetails() || result->IsProcedurePointer())
return false;
bool allResultSpecExprConstant = true;
auto visitor = [&](const Fortran::lower::SomeExpr &e) {
auto visitor = [&](const Fortran::lower::SomeExpr &e, bool) {
allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr(e);
};
walkResultLengths(visitor);
walkResultExtents(visitor);
return !allResultSpecExprConstant;
}

bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForDummyArgument(
const PassedEntity &arg) const {
bool allResultSpecExprConstant = true;
auto visitor = [&](const Fortran::lower::SomeExpr &e, bool) {
allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr(e);
};
walkDummyArgumentLengths(arg, visitor);
walkDummyArgumentExtents(arg, visitor);
return !allResultSpecExprConstant;
}

mlir::Value Fortran::lower::CallerInterface::getArgumentValue(
const semantics::Symbol &sym) const {
mlir::Location loc = converter.getCurrentLocation();
Expand All @@ -401,13 +453,36 @@ mlir::Value Fortran::lower::CallerInterface::getArgumentValue(
return actualInputs[mlirArgIndex];
}

const Fortran::semantics::Symbol *
Fortran::lower::CallerInterface::getDummySymbol(
const PassedEntity &passedEntity) const {
const Fortran::semantics::SubprogramDetails *ifaceDetails =
getInterfaceDetails();
if (!ifaceDetails)
return nullptr;
std::size_t argPosition = 0;
for (const auto &arg : getPassedArguments()) {
if (&arg == &passedEntity)
break;
++argPosition;
}
if (argPosition >= ifaceDetails->dummyArgs().size())
return nullptr;
return ifaceDetails->dummyArgs()[argPosition];
}

mlir::Type Fortran::lower::CallerInterface::getResultStorageType() const {
if (passedResult)
return fir::dyn_cast_ptrEleTy(inputs[passedResult->firArgument].type);
assert(saveResult && !outputs.empty());
return outputs[0].type;
}

mlir::Type Fortran::lower::CallerInterface::getDummyArgumentType(
const PassedEntity &passedEntity) const {
return inputs[passedEntity.firArgument].type;
}

const Fortran::semantics::Symbol &
Fortran::lower::CallerInterface::getResultSymbol() const {
mlir::Location loc = converter.getCurrentLocation();
Expand Down Expand Up @@ -975,12 +1050,6 @@ class Fortran::lower::CallInterfaceImpl {
Fortran::common::TypeCategory cat = dynamicType.category();
// DERIVED
if (cat == Fortran::common::TypeCategory::Derived) {
// TODO is kept under experimental flag until feature is complete.
if (dynamicType.IsPolymorphic() &&
!getConverter().getLoweringOptions().getPolymorphicTypeImpl())
TODO(interface.converter.getCurrentLocation(),
"support for polymorphic types");

if (dynamicType.IsUnlimitedPolymorphic())
return mlir::NoneType::get(&mlirContext);
return getConverter().genType(dynamicType.GetDerivedTypeSpec());
Expand Down Expand Up @@ -1387,6 +1456,17 @@ bool Fortran::lower::CallInterface<
return Fortran::semantics::IsFinalizable(*derived);
}

template <typename T>
bool Fortran::lower::CallInterface<
T>::PassedEntity::isSequenceAssociatedDescriptor() const {
if (!characteristics || passBy != PassEntityBy::Box)
return false;
const auto *dummy =
std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
&characteristics->u);
return dummy && dummy->type.CanBeSequenceAssociated();
}

template <typename T>
void Fortran::lower::CallInterface<T>::determineInterface(
bool isImplicit,
Expand Down
158 changes: 148 additions & 10 deletions flang/lib/Lower/ConvertCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,137 @@ static mlir::Value readDim3Value(fir::FirOpBuilder &builder, mlir::Location loc,
return hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{designate});
}

static mlir::Value remapActualToDummyDescriptor(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap,
const Fortran::lower::CallerInterface::PassedEntity &arg,
Fortran::lower::CallerInterface &caller, bool isBindcCall) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::IndexType idxTy = builder.getIndexType();
mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
Fortran::lower::StatementContext localStmtCtx;
auto lowerSpecExpr = [&](const auto &expr,
bool isAssumedSizeExtent) -> mlir::Value {
mlir::Value convertExpr = builder.createConvert(
loc, idxTy, fir::getBase(converter.genExprValue(expr, localStmtCtx)));
if (isAssumedSizeExtent)
return convertExpr;
return fir::factory::genMaxWithZero(builder, loc, convertExpr);
};
bool mapSymbols = caller.mustMapInterfaceSymbolsForDummyArgument(arg);
if (mapSymbols) {
symMap.pushScope();
const Fortran::semantics::Symbol *sym = caller.getDummySymbol(arg);
assert(sym && "call must have explicit interface to map interface symbols");
Fortran::lower::mapCallInterfaceSymbolsForDummyArgument(converter, caller,
symMap, *sym);
}
llvm::SmallVector<mlir::Value> extents;
llvm::SmallVector<mlir::Value> lengths;
mlir::Type dummyBoxType = caller.getDummyArgumentType(arg);
mlir::Type dummyBaseType = fir::unwrapPassByRefType(dummyBoxType);
if (dummyBaseType.isa<fir::SequenceType>())
caller.walkDummyArgumentExtents(
arg, [&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) {
extents.emplace_back(lowerSpecExpr(e, isAssumedSizeExtent));
});
mlir::Value shape;
if (!extents.empty()) {
if (isBindcCall) {
// Preserve zero lower bounds (see F'2023 18.5.3).
llvm::SmallVector<mlir::Value> lowerBounds(extents.size(), zero);
shape = builder.genShape(loc, lowerBounds, extents);
} else {
shape = builder.genShape(loc, extents);
}
}

hlfir::Entity explicitArgument = hlfir::Entity{caller.getInput(arg)};
mlir::Type dummyElementType = fir::unwrapSequenceType(dummyBaseType);
if (auto recType = llvm::dyn_cast<fir::RecordType>(dummyElementType))
if (recType.getNumLenParams() > 0)
TODO(loc, "sequence association of length parameterized derived type "
"dummy arguments");
if (fir::isa_char(dummyElementType))
lengths.emplace_back(hlfir::genCharLength(loc, builder, explicitArgument));
mlir::Value baseAddr =
hlfir::genVariableRawAddress(loc, builder, explicitArgument);
baseAddr = builder.createConvert(loc, fir::ReferenceType::get(dummyBaseType),
baseAddr);
mlir::Value mold;
if (fir::isPolymorphicType(dummyBoxType))
mold = explicitArgument;
mlir::Value remapped =
builder.create<fir::EmboxOp>(loc, dummyBoxType, baseAddr, shape,
/*slice=*/mlir::Value{}, lengths, mold);
if (mapSymbols)
symMap.popScope();
return remapped;
}

/// Create a descriptor for sequenced associated descriptor that are passed
/// by descriptor. Sequence association (F'2023 15.5.2.12) implies that the
/// dummy shape and rank need to not be the same as the actual argument. This
/// helper creates a descriptor based on the dummy shape and rank (sequence
/// association can only happen with explicit and assumed-size array) so that it
/// is safe to assume the rank of the incoming descriptor inside the callee.
/// This helper must be called once all the actual arguments have been lowered
/// and placed inside "caller". Copy-in/copy-out must already have been
/// generated if needed using the actual argument shape (the dummy shape may be
/// assumed-size).
static void remapActualToDummyDescriptors(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap,
const Fortran::lower::PreparedActualArguments &loweredActuals,
Fortran::lower::CallerInterface &caller, bool isBindcCall) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
for (auto [preparedActual, arg] :
llvm::zip(loweredActuals, caller.getPassedArguments())) {
if (arg.isSequenceAssociatedDescriptor()) {
if (!preparedActual.value().handleDynamicOptional()) {
mlir::Value remapped = remapActualToDummyDescriptor(
loc, converter, symMap, arg, caller, isBindcCall);
caller.placeInput(arg, remapped);
} else {
// Absent optional actual argument descriptor cannot be read and
// remapped unconditionally.
mlir::Type dummyType = caller.getDummyArgumentType(arg);
mlir::Value isPresent = preparedActual.value().getIsPresent();
auto &argLambdaCapture = arg;
mlir::Value remapped =
builder
.genIfOp(loc, {dummyType}, isPresent,
/*withElseRegion=*/true)
.genThen([&]() {
mlir::Value newBox = remapActualToDummyDescriptor(
loc, converter, symMap, argLambdaCapture, caller,
isBindcCall);
builder.create<fir::ResultOp>(loc, newBox);
})
.genElse([&]() {
mlir::Value absent =
builder.create<fir::AbsentOp>(loc, dummyType);
builder.create<fir::ResultOp>(loc, absent);
})
.getResults()[0];
caller.placeInput(arg, remapped);
}
}
}
}

std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
std::optional<mlir::Type> resultType, bool isElemental) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
using PassBy = Fortran::lower::CallerInterface::PassEntityBy;
// Handle cases where caller must allocate the result or a fir.box for it.
bool mustPopSymMap = false;
if (caller.mustMapInterfaceSymbols()) {
if (caller.mustMapInterfaceSymbolsForResult()) {
symMap.pushScope();
mustPopSymMap = true;
Fortran::lower::mapCallInterfaceSymbols(converter, caller, symMap);
Fortran::lower::mapCallInterfaceSymbolsForResult(converter, caller, symMap);
}
// If this is an indirect call, retrieve the function address. Also retrieve
// the result length if this is a character function (note that this length
Expand Down Expand Up @@ -221,12 +339,16 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult(
return {};
mlir::Type type = caller.getResultStorageType();
if (type.isa<fir::SequenceType>())
caller.walkResultExtents([&](const Fortran::lower::SomeExpr &e) {
extents.emplace_back(lowerSpecExpr(e));
});
caller.walkResultLengths([&](const Fortran::lower::SomeExpr &e) {
lengths.emplace_back(lowerSpecExpr(e));
});
caller.walkResultExtents(
[&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) {
assert(!isAssumedSizeExtent && "result cannot be assumed-size");
extents.emplace_back(lowerSpecExpr(e));
});
caller.walkResultLengths(
[&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) {
assert(!isAssumedSizeExtent && "result cannot be assumed-size");
lengths.emplace_back(lowerSpecExpr(e));
});

// Result length parameters should not be provided to box storage
// allocation and save_results, but they are still useful information to
Expand Down Expand Up @@ -1056,10 +1178,16 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
// Create dummy type with actual argument rank when the dummy is an assumed
// rank. That way, all the operation to create dummy descriptors are ranked if
// the actual argument is ranked, which allows simple code generation.
// Also do the same when the dummy is a sequence associated descriptor
// because the actual shape/rank may mismatch with the dummy, and the dummy
// may be an assumed-size array, so any descriptor manipulation should use the
// actual argument shape information. A descriptor with the dummy shape
// information will be created later when all actual arguments are ready.
mlir::Type dummyTypeWithActualRank = dummyType;
if (auto baseBoxDummy = mlir::dyn_cast<fir::BaseBoxType>(dummyType))
if (baseBoxDummy.isAssumedRank() ||
arg.testTKR(Fortran::common::IgnoreTKR::Rank))
arg.testTKR(Fortran::common::IgnoreTKR::Rank) ||
arg.isSequenceAssociatedDescriptor())
dummyTypeWithActualRank =
baseBoxDummy.getBoxTypeWithNewShape(actual.getType());
// Preserve the actual type in the argument preparation in case IgnoreTKR(t)
Expand Down Expand Up @@ -1342,6 +1470,7 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
mlir::FunctionType callSiteType, CallContext &callContext) {
using PassBy = Fortran::lower::CallerInterface::PassEntityBy;
mlir::Location loc = callContext.loc;
bool mustRemapActualToDummyDescriptors = false;
fir::FirOpBuilder &builder = callContext.getBuilder();
llvm::SmallVector<CallCleanUp> callCleanUps;
for (auto [preparedActual, arg] :
Expand Down Expand Up @@ -1398,6 +1527,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
callCleanUps.append(preparedDummy.cleanups.rbegin(),
preparedDummy.cleanups.rend());
caller.placeInput(arg, preparedDummy.dummy);
if (arg.passBy == PassBy::Box)
mustRemapActualToDummyDescriptors |=
arg.isSequenceAssociatedDescriptor();
} break;
case PassBy::BoxProcRef: {
PreparedDummyArgument preparedDummy =
Expand Down Expand Up @@ -1490,6 +1622,12 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
} break;
}
}
// Handle cases where caller must allocate the result or a fir.box for it.
if (mustRemapActualToDummyDescriptors)
remapActualToDummyDescriptors(loc, callContext.converter,
callContext.symMap, loweredActuals, caller,
callContext.isBindcCall());

// Prepare lowered arguments according to the interface
// and map the lowered values to the dummy
// arguments.
Expand Down
4 changes: 0 additions & 4 deletions flang/lib/Lower/ConvertType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,6 @@ struct TypeBuilderImpl {
llvm::SmallVector<Fortran::lower::LenParameterTy> params;
translateLenParameters(params, tySpec->category(), ultimate);
ty = genFIRType(context, tySpec->category(), kind, params);
} else if (type->IsPolymorphic() &&
!converter.getLoweringOptions().getPolymorphicTypeImpl()) {
// TODO is kept under experimental flag until feature is complete.
TODO(loc, "support for polymorphic types");
} else if (type->IsUnlimitedPolymorphic()) {
ty = mlir::NoneType::get(context);
} else if (const Fortran::semantics::DerivedTypeSpec *tySpec =
Expand Down
29 changes: 22 additions & 7 deletions flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2260,19 +2260,20 @@ void Fortran::lower::instantiateVariable(AbstractConverter &converter,
instantiateLocal(converter, var, symMap);
}

void Fortran::lower::mapCallInterfaceSymbols(
AbstractConverter &converter, const Fortran::lower::CallerInterface &caller,
SymMap &symMap) {
static void
mapCallInterfaceSymbol(const Fortran::semantics::Symbol &interfaceSymbol,
Fortran::lower::AbstractConverter &converter,
const Fortran::lower::CallerInterface &caller,
Fortran::lower::SymMap &symMap) {
Fortran::lower::AggregateStoreMap storeMap;
const Fortran::semantics::Symbol &result = caller.getResultSymbol();
for (Fortran::lower::pft::Variable var :
Fortran::lower::pft::getDependentVariableList(result)) {
Fortran::lower::pft::getDependentVariableList(interfaceSymbol)) {
if (var.isAggregateStore()) {
instantiateVariable(converter, var, symMap, storeMap);
continue;
}
const Fortran::semantics::Symbol &sym = var.getSymbol();
if (&sym == &result)
if (&sym == &interfaceSymbol)
continue;
const auto *hostDetails =
sym.detailsIf<Fortran::semantics::HostAssocDetails>();
Expand All @@ -2293,7 +2294,8 @@ void Fortran::lower::mapCallInterfaceSymbols(
// instantiateVariable that would try to allocate a new storage.
continue;
}
if (Fortran::semantics::IsDummy(sym) && sym.owner() == result.owner()) {
if (Fortran::semantics::IsDummy(sym) &&
sym.owner() == interfaceSymbol.owner()) {
// Get the argument for the dummy argument symbols of the current call.
symMap.addSymbol(sym, caller.getArgumentValue(sym));
// All the properties of the dummy variable may not come from the actual
Expand All @@ -2307,6 +2309,19 @@ void Fortran::lower::mapCallInterfaceSymbols(
}
}

void Fortran::lower::mapCallInterfaceSymbolsForResult(
AbstractConverter &converter, const Fortran::lower::CallerInterface &caller,
SymMap &symMap) {
const Fortran::semantics::Symbol &result = caller.getResultSymbol();
mapCallInterfaceSymbol(result, converter, caller, symMap);
}

void Fortran::lower::mapCallInterfaceSymbolsForDummyArgument(
AbstractConverter &converter, const Fortran::lower::CallerInterface &caller,
SymMap &symMap, const Fortran::semantics::Symbol &dummySymbol) {
mapCallInterfaceSymbol(dummySymbol, converter, caller, symMap);
}

void Fortran::lower::mapSymbolAttributes(
AbstractConverter &converter, const Fortran::semantics::SymbolRef &symbol,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
Expand Down
37 changes: 31 additions & 6 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,25 @@ addUseDeviceClause(Fortran::lower::AbstractConverter &converter,
useDeviceSymbols.push_back(object.id());
}

static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
llvm::SmallVectorImpl<mlir::Value> &upperBound,
llvm::SmallVectorImpl<mlir::Value> &step,
std::size_t loopVarTypeSize) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
// The types of lower bound, upper bound, and step are converted into the
// type of the loop variable if necessary.
mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) {
lowerBound[it] =
firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]);
upperBound[it] =
firOpBuilder.createConvert(loc, loopVarType, upperBound[it]);
step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]);
}
}

//===----------------------------------------------------------------------===//
// ClauseProcessor unique clauses
//===----------------------------------------------------------------------===//
Expand All @@ -217,8 +236,7 @@ bool ClauseProcessor::processCollapse(
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
llvm::SmallVectorImpl<mlir::Value> &upperBound,
llvm::SmallVectorImpl<mlir::Value> &step,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv,
std::size_t &loopVarTypeSize) const {
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv) const {
bool found = false;
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

Expand All @@ -236,7 +254,7 @@ bool ClauseProcessor::processCollapse(
found = true;
}

loopVarTypeSize = 0;
std::size_t loopVarTypeSize = 0;
do {
Fortran::lower::pft::Evaluation *doLoop =
&doConstructEval->getFirstNestedEvaluation();
Expand Down Expand Up @@ -267,6 +285,9 @@ bool ClauseProcessor::processCollapse(
&*std::next(doConstructEval->getNestedEvaluations().begin());
} while (collapseValue > 0);

convertLoopBounds(converter, currentLocation, lowerBound, upperBound, step,
loopVarTypeSize);

return found;
}

Expand Down Expand Up @@ -577,7 +598,7 @@ class TypeInfo {
}

// Returns the shape of array types.
const llvm::SmallVector<int64_t> &getShape() const { return shape; }
llvm::ArrayRef<int64_t> getShape() const { return shape; }

// Is the type inside a box?
bool isBox() const { return inBox; }
Expand Down Expand Up @@ -788,8 +809,8 @@ bool ClauseProcessor::processLink(
mlir::omp::MapInfoOp
createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name,
mlir::SmallVector<mlir::Value> bounds,
mlir::SmallVector<mlir::Value> members, uint64_t mapType,
llvm::ArrayRef<mlir::Value> bounds,
llvm::ArrayRef<mlir::Value> members, uint64_t mapType,
mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy,
bool isVal) {
if (auto boxTy = baseAddr.getType().dyn_cast<fir::BaseBoxType>()) {
Expand Down Expand Up @@ -907,6 +928,7 @@ bool ClauseProcessor::processMap(
bool ClauseProcessor::processReduction(
mlir::Location currentLocation,
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
llvm::SmallVectorImpl<mlir::Type> &reductionTypes,
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols)
const {
Expand All @@ -916,6 +938,9 @@ bool ClauseProcessor::processReduction(
ReductionProcessor rp;
rp.addReductionDecl(currentLocation, converter, clause, reductionVars,
reductionDeclSymbols, reductionSymbols);
reductionTypes.reserve(reductionVars.size());
llvm::transform(reductionVars, std::back_inserter(reductionTypes),
[](mlir::Value v) { return v.getType(); });
});
}

Expand Down
15 changes: 7 additions & 8 deletions flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,12 @@ class ClauseProcessor {
clauses(makeList(clauses, semaCtx)) {}

// 'Unique' clauses: They can appear at most once in the clause list.
bool
processCollapse(mlir::Location currentLocation,
Fortran::lower::pft::Evaluation &eval,
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
llvm::SmallVectorImpl<mlir::Value> &upperBound,
llvm::SmallVectorImpl<mlir::Value> &step,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv,
std::size_t &loopVarTypeSize) const;
bool processCollapse(
mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval,
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
llvm::SmallVectorImpl<mlir::Value> &upperBound,
llvm::SmallVectorImpl<mlir::Value> &step,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv) const;
bool processDefault() const;
bool processDevice(Fortran::lower::StatementContext &stmtCtx,
mlir::Value &result) const;
Expand Down Expand Up @@ -126,6 +124,7 @@ class ClauseProcessor {
bool
processReduction(mlir::Location currentLocation,
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
llvm::SmallVectorImpl<mlir::Type> &reductionTypes,
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
*reductionSymbols = nullptr) const;
Expand Down
131 changes: 38 additions & 93 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,24 +214,6 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
firOpBuilder.restoreInsertionPoint(insPt);
}

static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
std::size_t loopVarTypeSize) {
// OpenMP runtime requires 32-bit or 64-bit loop variables.
loopVarTypeSize = loopVarTypeSize * 8;
if (loopVarTypeSize < 32) {
loopVarTypeSize = 32;
} else if (loopVarTypeSize > 64) {
loopVarTypeSize = 64;
mlir::emitWarning(converter.getCurrentLocation(),
"OpenMP loop iteration variable cannot have more than 64 "
"bits size and will be narrowed into 64 bits.");
}
assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) &&
"OpenMP loop iteration variable size must be transformed into 32-bit "
"or 64-bit");
return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
}

static mlir::Operation *
createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
mlir::Location loc, mlir::Value indexVal,
Expand Down Expand Up @@ -287,9 +269,9 @@ struct OpWithBodyGenInfo {
return *this;
}

OpWithBodyGenInfo &
setReductions(llvm::SmallVector<const Fortran::semantics::Symbol *> *value1,
llvm::SmallVector<mlir::Type> *value2) {
OpWithBodyGenInfo &setReductions(
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *value1,
llvm::SmallVectorImpl<mlir::Type> *value2) {
reductionSymbols = value1;
reductionTypes = value2;
return *this;
Expand Down Expand Up @@ -317,10 +299,10 @@ struct OpWithBodyGenInfo {
/// [in] if provided, processes the construct's data-sharing attributes.
DataSharingProcessor *dsp = nullptr;
/// [in] if provided, list of reduction symbols
llvm::SmallVector<const Fortran::semantics::Symbol *> *reductionSymbols =
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols =
nullptr;
/// [in] if provided, list of reduction types
llvm::SmallVector<mlir::Type> *reductionTypes = nullptr;
llvm::SmallVectorImpl<mlir::Type> *reductionTypes = nullptr;
/// [in] if provided, emits the op's region entry. Otherwise, an emtpy block
/// is created in the region.
GenOMPRegionEntryCBFn genRegionEntryCB = nullptr;
Expand Down Expand Up @@ -465,11 +447,9 @@ static void genBodyOfTargetDataOp(
Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semaCtx,
Fortran::lower::pft::Evaluation &eval, bool genNested,
mlir::omp::DataOp &dataOp,
const llvm::SmallVector<mlir::Type> &useDeviceTypes,
const llvm::SmallVector<mlir::Location> &useDeviceLocs,
const llvm::SmallVector<const Fortran::semantics::Symbol *>
&useDeviceSymbols,
mlir::omp::DataOp &dataOp, llvm::ArrayRef<mlir::Type> useDeviceTypes,
llvm::ArrayRef<mlir::Location> useDeviceLocs,
llvm::ArrayRef<const Fortran::semantics::Symbol *> useDeviceSymbols,
const mlir::Location &currentLocation) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
mlir::Region &region = dataOp.getRegion();
Expand Down Expand Up @@ -570,6 +550,7 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
mlir::omp::ClauseProcBindKindAttr procBindKindAttr;
llvm::SmallVector<mlir::Value> allocateOperands, allocatorOperands,
reductionVars;
llvm::SmallVector<mlir::Type> reductionTypes;
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
llvm::SmallVector<const Fortran::semantics::Symbol *> reductionSymbols;

Expand All @@ -580,13 +561,8 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
cp.processDefault();
cp.processAllocate(allocatorOperands, allocateOperands);
if (!outerCombined)
cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols,
&reductionSymbols);

llvm::SmallVector<mlir::Type> reductionTypes;
reductionTypes.reserve(reductionVars.size());
llvm::transform(reductionVars, std::back_inserter(reductionTypes),
[](mlir::Value v) { return v.getType(); });
cp.processReduction(currentLocation, reductionVars, reductionTypes,
reductionDeclSymbols, &reductionSymbols);

auto reductionCallback = [&](mlir::Operation *op) {
llvm::SmallVector<mlir::Location> locs(reductionVars.size(),
Expand Down Expand Up @@ -814,11 +790,12 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter,
// clause. Support for such list items in a use_device_ptr clause
// is deprecated."
static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
llvm::SmallVector<mlir::Value> &devicePtrOperands,
llvm::SmallVector<mlir::Value> &deviceAddrOperands,
llvm::SmallVector<mlir::Type> &useDeviceTypes,
llvm::SmallVector<mlir::Location> &useDeviceLocs,
llvm::SmallVector<const Fortran::semantics::Symbol *> &useDeviceSymbols) {
llvm::SmallVectorImpl<mlir::Value> &devicePtrOperands,
llvm::SmallVectorImpl<mlir::Value> &deviceAddrOperands,
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
&useDeviceSymbols) {
auto moveElementToBack = [](size_t idx, auto &vector) {
auto *iter = std::next(vector.begin(), idx);
vector.push_back(*iter);
Expand Down Expand Up @@ -951,15 +928,15 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter,

// This functions creates a block for the body of the targetOp's region. It adds
// all the symbols present in mapSymbols as block arguments to this block.
static void genBodyOfTargetOp(
Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semaCtx,
Fortran::lower::pft::Evaluation &eval, bool genNested,
mlir::omp::TargetOp &targetOp,
const llvm::SmallVector<mlir::Type> &mapSymTypes,
const llvm::SmallVector<mlir::Location> &mapSymLocs,
const llvm::SmallVector<const Fortran::semantics::Symbol *> &mapSymbols,
const mlir::Location &currentLocation) {
static void
genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semaCtx,
Fortran::lower::pft::Evaluation &eval, bool genNested,
mlir::omp::TargetOp &targetOp,
llvm::ArrayRef<mlir::Type> mapSymTypes,
llvm::ArrayRef<mlir::Location> mapSymLocs,
llvm::ArrayRef<const Fortran::semantics::Symbol *> mapSymbols,
const mlir::Location &currentLocation) {
assert(mapSymTypes.size() == mapSymLocs.size());

fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
Expand Down Expand Up @@ -1469,29 +1446,10 @@ genOMP(Fortran::lower::AbstractConverter &converter,
standaloneConstruct.u);
}

static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
llvm::SmallVectorImpl<mlir::Value> &upperBound,
llvm::SmallVectorImpl<mlir::Value> &step,
std::size_t loopVarTypeSize) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
// The types of lower bound, upper bound, and step are converted into the
// type of the loop variable if necessary.
mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) {
lowerBound[it] =
firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]);
upperBound[it] =
firOpBuilder.createConvert(loc, loopVarType, upperBound[it]);
step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]);
}
}

static llvm::SmallVector<const Fortran::semantics::Symbol *>
genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
mlir::Location &loc,
const llvm::SmallVector<const Fortran::semantics::Symbol *> &args) {
llvm::ArrayRef<const Fortran::semantics::Symbol *> args) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
auto &region = op->getRegion(0);

Expand All @@ -1512,16 +1470,16 @@ genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
}
firOpBuilder.setInsertionPointAfter(storeOp);

return args;
return llvm::SmallVector<const Fortran::semantics::Symbol *>(args);
}

static llvm::SmallVector<const Fortran::semantics::Symbol *>
genLoopAndReductionVars(
mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
mlir::Location &loc,
const llvm::SmallVector<const Fortran::semantics::Symbol *> &loopArgs,
const llvm::SmallVector<const Fortran::semantics::Symbol *> &reductionArgs,
llvm::SmallVector<mlir::Type> &reductionTypes) {
llvm::ArrayRef<const Fortran::semantics::Symbol *> loopArgs,
llvm::ArrayRef<const Fortran::semantics::Symbol *> reductionArgs,
llvm::SmallVectorImpl<mlir::Type> &reductionTypes) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

llvm::SmallVector<mlir::Type> blockArgTypes;
Expand Down Expand Up @@ -1564,7 +1522,7 @@ genLoopAndReductionVars(
converter.bindSymbol(*arg, prv);
}

return loopArgs;
return llvm::SmallVector<const Fortran::semantics::Symbol *>(loopArgs);
}

static void
Expand All @@ -1583,16 +1541,15 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars;
llvm::SmallVector<mlir::Value> alignedVars, nontemporalVars;
llvm::SmallVector<const Fortran::semantics::Symbol *> iv;
llvm::SmallVector<mlir::Type> reductionTypes;
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
mlir::omp::ClauseOrderKindAttr orderClauseOperand;
mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand;
std::size_t loopVarTypeSize;

ClauseProcessor cp(converter, semaCtx, loopOpClauseList);
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv,
loopVarTypeSize);
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv);
cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
cp.processReduction(loc, reductionVars, reductionDeclSymbols);
cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols);
cp.processIf(clause::If::DirectiveNameModifier::Simd, ifClauseOperand);
cp.processSimdlen(simdlenClauseOperand);
cp.processSafelen(safelenClauseOperand);
Expand All @@ -1602,9 +1559,6 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
Fortran::parser::OmpClause::Nontemporal,
Fortran::parser::OmpClause::Order>(loc, ompDirective);

convertLoopBounds(converter, loc, lowerBound, upperBound, step,
loopVarTypeSize);

mlir::TypeRange resultType;
auto simdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
loc, resultType, lowerBound, upperBound, step, alignedVars,
Expand Down Expand Up @@ -1642,27 +1596,23 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars;
llvm::SmallVector<mlir::Value> linearVars, linearStepVars;
llvm::SmallVector<const Fortran::semantics::Symbol *> iv;
llvm::SmallVector<mlir::Type> reductionTypes;
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
llvm::SmallVector<const Fortran::semantics::Symbol *> reductionSymbols;
mlir::omp::ClauseOrderKindAttr orderClauseOperand;
mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand;
mlir::UnitAttr nowaitClauseOperand, byrefOperand, scheduleSimdClauseOperand;
mlir::IntegerAttr orderedClauseOperand;
mlir::omp::ScheduleModifierAttr scheduleModClauseOperand;
std::size_t loopVarTypeSize;

ClauseProcessor cp(converter, semaCtx, beginClauseList);
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv,
loopVarTypeSize);
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv);
cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
cp.processReduction(loc, reductionVars, reductionDeclSymbols,
cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols,
&reductionSymbols);
cp.processTODO<Fortran::parser::OmpClause::Linear,
Fortran::parser::OmpClause::Order>(loc, ompDirective);

convertLoopBounds(converter, loc, lowerBound, upperBound, step,
loopVarTypeSize);

if (ReductionProcessor::doReductionByRef(reductionVars))
byrefOperand = firOpBuilder.getUnitAttr();

Expand Down Expand Up @@ -1703,11 +1653,6 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
auto *nestedEval = getCollapsedLoopEval(
eval, Fortran::lower::getCollapseValue(beginClauseList));

llvm::SmallVector<mlir::Type> reductionTypes;
reductionTypes.reserve(reductionVars.size());
llvm::transform(reductionVars, std::back_inserter(reductionTypes),
[](mlir::Value v) { return v.getType(); });

auto ivCallback = [&](mlir::Operation *op) {
return genLoopAndReductionVars(op, converter, loc, iv, reductionSymbols,
reductionTypes);
Expand Down
19 changes: 19 additions & 0 deletions flang/lib/Lower/OpenMP/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <flang/Lower/AbstractConverter.h>
#include <flang/Lower/ConvertType.h>
#include <flang/Optimizer/Builder/FIRBuilder.h>
#include <flang/Parser/parse-tree.h>
#include <flang/Parser/tools.h>
#include <flang/Semantics/tools.h>
Expand Down Expand Up @@ -70,6 +71,24 @@ void genObjectList2(const Fortran::parser::OmpObjectList &objectList,
}
}

mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
std::size_t loopVarTypeSize) {
// OpenMP runtime requires 32-bit or 64-bit loop variables.
loopVarTypeSize = loopVarTypeSize * 8;
if (loopVarTypeSize < 32) {
loopVarTypeSize = 32;
} else if (loopVarTypeSize > 64) {
loopVarTypeSize = 64;
mlir::emitWarning(converter.getCurrentLocation(),
"OpenMP loop iteration variable cannot have more than 64 "
"bits size and will be narrowed into 64 bits.");
}
assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) &&
"OpenMP loop iteration variable size must be transformed into 32-bit "
"or 64-bit");
return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
}

void gatherFuncAndVarSyms(
const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
Expand Down
7 changes: 5 additions & 2 deletions flang/lib/Lower/OpenMP/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ using DeclareTargetCapturePair =
mlir::omp::MapInfoOp
createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name,
mlir::SmallVector<mlir::Value> bounds,
mlir::SmallVector<mlir::Value> members, uint64_t mapType,
mlir::ArrayRef<mlir::Value> bounds,
mlir::ArrayRef<mlir::Value> members, uint64_t mapType,
mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy,
bool isVal = false);

mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
std::size_t loopVarTypeSize);

void gatherFuncAndVarSyms(
const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause);
Expand Down
2 changes: 0 additions & 2 deletions flang/test/Driver/driver-help-hidden.f90
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@
! CHECK-NEXT: Do not use HLFIR lowering (deprecated)
! CHECK-NEXT: -flang-experimental-hlfir
! CHECK-NEXT: Use HLFIR lowering (experimental)
! CHECK-NEXT: -flang-experimental-polymorphism
! CHECK-NEXT: Enable Fortran 2003 polymorphism (experimental)
! CHECK-NEXT: -flarge-sizes Use INTEGER(KIND=8) for the result type in size-related intrinsics
! CHECK-NEXT: -flogical-abbreviations Enable logical abbreviations
! CHECK-NEXT: -flto=auto Enable LTO in 'full' mode
Expand Down
10 changes: 0 additions & 10 deletions flang/test/Driver/flang-experimental-polymorphism-flag.f90

This file was deleted.

2 changes: 0 additions & 2 deletions flang/test/Driver/frontend-forwarding.f90
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
! RUN: -fomit-frame-pointer \
! RUN: -fpass-plugin=Bye%pluginext \
! RUN: -fversion-loops-for-stride \
! RUN: -flang-experimental-polymorphism \
! RUN: -flang-experimental-hlfir \
! RUN: -flang-deprecated-no-hlfir \
! RUN: -fno-ppc-native-vector-element-order \
Expand Down Expand Up @@ -49,7 +48,6 @@
! CHECK: "-fconvert=little-endian"
! CHECK: "-fpass-plugin=Bye
! CHECK: "-fversion-loops-for-stride"
! CHECK: "-flang-experimental-polymorphism"
! CHECK: "-flang-experimental-hlfir"
! CHECK: "-flang-deprecated-no-hlfir"
! CHECK: "-fno-ppc-native-vector-element-order"
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Fir/dispatch.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s --check-prefix=BT
! RUN: bbc -emit-hlfir %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s --check-prefix=BT

! Tests codegen of fir.dispatch operation. This test is intentionally run from
! Fortran through bbc and tco so we have all the binding tables lowered to FIR
Expand Down
2 changes: 1 addition & 1 deletion flang/test/HLFIR/assumed-type-actual-args.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test lowering to FIR of actual arguments that are assumed type
! variables (Fortran 2018 7.3.2.2 point 3).
! RUN: bbc --polymorphic-type -emit-hlfir -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

subroutine test1(x)
interface
Expand Down
2 changes: 1 addition & 1 deletion flang/test/HLFIR/boxchar_emboxing.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s

! CHECK-LABEL: func.func @_QPtest1(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<none> {fir.bindc_name = "x"}) {
Expand Down
2 changes: 1 addition & 1 deletion flang/test/HLFIR/call_with_poly_dummy.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s

! Test passing arguments to subprograms with polymorphic dummy arguments.

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test actual TARGET argument association to dummy POINTER:
! RUN: bbc -emit-hlfir --polymorphic-type -o - -I nowhere %s 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -o - -I nowhere %s 2>&1 | FileCheck %s

module target_to_pointer_types
type t1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/allocatable-return.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-hlfir --polymorphic-type -I nowhere %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir -I nowhere %s -o - | FileCheck %s

! Test allocatable return.
! Allocatable arrays must have default runtime lbounds after the return.
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/array-ctor-derived.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of derived type array constructors to HLFIR.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

module types
type simple
Expand Down
309 changes: 309 additions & 0 deletions flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/calls-assumed-shape.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test lowering of calls involving assumed shape arrays or arrays with
! VALUE attribute.
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

subroutine test_assumed_to_assumed(x)
interface
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

! Test when constant argument are copied in memory
! and passed to polymorphic arguments.
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/calls-optional.f90
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
! that is syntactically present, but may be absent at runtime (is
! an optional or a pointer/allocatable).
!
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

subroutine optional_copy_in_out(x)
interface
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test passing rank 2 CLASS(*) deferred shape to assumed size assumed type
! This requires copy-in/copy-out logic.
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

subroutine pass_poly_to_assumed_type_assumed_size(x)
class(*), target :: x(:,:)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/convert-mbox-to-value.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test conversion of MutableBoxValue to value.
! RUN: bbc -emit-hlfir -polymorphic-type -I nowhere %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir -I nowhere %s -o - | FileCheck %s

subroutine test_int_allocatable(a)
integer, allocatable :: a
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/designators-component-ref.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of component reference to HLFIR
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
module comp_ref
type t1
integer :: scalar_i
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test non-contiguous slice of parameter array.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
subroutine test2(i)
integer, parameter :: a(*,*) = reshape( [ 1,2,3,4 ], [ 2,2 ])
integer :: x(2)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/elemental-array-ops.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of elemental intrinsic operations with array arguments to HLFIR
! RUN: bbc -emit-hlfir --polymorphic-type -I nowhere -o - %s 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -I nowhere -o - %s 2>&1 | FileCheck %s

subroutine binary(x, y)
integer :: x(100), y(100)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test that the produced hlfir.elemental had proper result type and the mold.
! RUN: bbc --emit-hlfir --polymorphic-type -I nowhere -o - %s | FileCheck %s
! RUN: bbc --emit-hlfir -I nowhere -o - %s | FileCheck %s

subroutine test_polymorphic_merge(x, y, r, m)
type t
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test lowering of user defined elemental procedure reference to HLFIR
! With polymorphic arguments.
! RUN: bbc -emit-hlfir -I nw -polymorphic-type -o - %s 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -I nw -o - %s 2>&1 | FileCheck %s
module def_some_types
type :: t
integer :: i
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/function-return-as-expr.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nowhere 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s -I nowhere 2>&1 | FileCheck %s

module types
type t1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/function-return-destroy.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nowhere | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - -I nowhere | FileCheck %s

module types
type t1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test passing mismatching rank arguments to unlimited polymorphic
! dummy with IGNORE_TKR(R).
! RUN: bbc -emit-hlfir -polymorphic-type -o - -I nowhere %s 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -o - -I nowhere %s 2>&1 | FileCheck %s

module m
interface
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/ignore-type-assumed-shape.f90
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
! dummy has IGNORE_TKR(t). The descriptor should be prepared
! according to the actual argument type, but its bounds and
! attributes should still be set as expected for the dummy.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

module tkr_ifaces
interface
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test that allocatable components of non pointer/non allocatable INTENT(OUT)
! dummy arguments are deallocated.
! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nowhere | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - -I nowhere | FileCheck %s

subroutine test_intentout_component_deallocate(a)
type :: t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/internal-procedures-polymorphic.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test lowering of internal procedure capturing OPTIONAL polymorphic
! objects.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nw | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s -I nw | FileCheck %s


module captured_optional_polymorphic
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/intrinsic-assumed-type.f90
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
! arguments. These are a bit special because semantics do not represent
! assumed types actual arguments with an evaluate::Expr like for usual
! arguments.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

subroutine assumed_type_to_intrinsic(a)
type(*) :: a(:)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/parent-component-ref.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of parent component references to HLFIR.
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s -I nw | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s -I nw | FileCheck %s

module pc_types
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test passing polymorphic expression for non-polymorphic contiguous
! dummy argument:
! RUN: bbc -emit-hlfir --polymorphic-type -o - -I nowhere %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - -I nowhere %s | FileCheck %s

module types
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/polymorphic-expressions.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nowhere | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s -I nowhere | FileCheck %s

module polymorphic_expressions_types
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of NOPASS procedure pointers components.
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

module proc_comp_defs
interface
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of PASS procedure pointers components.
! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

module m
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/select-type-selector.f90
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
! (16.9.109) applied to the corresponding dimension of selector. The upper bound of each dimension is one less
! than the sum of the lower bound and the extent.

! RUN: bbc -emit-hlfir -polymorphic-type -I nowhere -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -I nowhere -o - %s | FileCheck %s

subroutine test()
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/transpose.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of TRANSPOSE intrinsic to HLFIR
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s

subroutine transpose1(m, res)
integer :: m(1,2), res(2, 1)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/type-bound-call-mismatch.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test interface that lowering handles small interface mismatch with
! type bound procedures.
! RUN: bbc -emit-hlfir --polymorphic-type %s -o - -I nw | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s

module dispatch_mismatch
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/HLFIR/vector-subscript-as-value.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test lowering of vector subscript designators outside of the
! assignment left-and side and input IO context.
! RUN: bbc -emit-hlfir -o - -I nw %s --polymorphic-type 2>&1 | FileCheck %s
! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s

subroutine foo(x, y)
integer :: x(100)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/Intrinsics/extends_type_of.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module extends_type_of_mod

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/Intrinsics/same_type_as.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module same_type_as_mod

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/Intrinsics/sizeof.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test SIZEOF lowering for polymorphic entities.
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

integer(8) function test1(x)
class(*) :: x
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/Intrinsics/spread.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module spread_mod

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/Intrinsics/storage_size.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module storage_size_test
type :: p1
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/allocatable-polymorphic.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-hlfir %s -o - | tco | FileCheck %s --check-prefix=LLVM
! RUN: bbc --use-desc-for-alloc=false -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc --use-desc-for-alloc=false -emit-hlfir %s -o - | tco | FileCheck %s --check-prefix=LLVM

module poly
type p1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/allocatable-return.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -emit-fir -hlfir=false --polymorphic-type -I nowhere %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false -I nowhere %s -o - | FileCheck %s

! Test allocatable return.
! Allocatable arrays must have default runtime lbounds after the return.
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/assumed-type.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module assumed_type_test

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/default-initialization.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test default initialization of local and dummy variables (dynamic initialization)
! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module test_dinit
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/derived-type-finalization.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test derived type finalization
! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s

! Missing tests:
! - finalization within BLOCK construct
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/dispatch-table.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir %s -o - | FileCheck %s
! RUN: bbc -emit-fir %s -o - | FileCheck %s

! Tests the generation of fir.type_info operations.

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/dispatch.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s

! Tests the different possible type involving polymorphic entities.

Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/intentout-deallocate.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Test correct deallocation of intent(out) allocatables.
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s --check-prefixes=CHECK,FIR
! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nw | FileCheck %s --check-prefixes=CHECK,HLFIR
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes=CHECK,FIR
! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s --check-prefixes=CHECK,HLFIR

module mod1
type, bind(c) :: t1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/io-derived-type-2.f90
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
! Check that InputDerivedType/OutputDeriverType APIs are used
! for io of derived types.
! RUN: bbc -polymorphic-type -emit-fir -o - %s | FileCheck %s
! RUN: bbc -emit-fir -o - %s | FileCheck %s

module p
type :: person
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/io-derived-type.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false -o - %s | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s

module m
type t
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/nullify-polymorphic.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s

module poly
type p1
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/pass-null-for-class-arg.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! RUN: bbc -emit-fir -polymorphic-type %s -o - | FileCheck %s --check-prefix=FIR
! RUN: bbc -emit-fir -polymorphic-type -hlfir %s -o - | FileCheck %s --check-prefix=HLFIR
! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR
! RUN: bbc -emit-fir -hlfir %s -o - | FileCheck %s --check-prefix=HLFIR

subroutine test
interface
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/pointer-association-polymorphic.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module poly
type p1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/pointer-disassociate.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test lowering of pointer disassociation
! RUN: bbc -emit-fir -hlfir=false --polymorphic-type %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s


! -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/polymorphic-temp.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! Test creation of temporary from polymorphic enities
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module poly_tmp
type p1
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/polymorphic-types.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

! Tests the different possible type involving polymorphic entities.

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/polymorphic.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s

! Tests various aspect of the lowering of polymorphic entities.

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/select-type-2.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s
module select_type_2
type p1
integer :: a
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/select-type.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck --check-prefix=CFG %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck --check-prefix=CFG %s
module select_type_lower_test
type p1
integer :: a
Expand Down
6 changes: 0 additions & 6 deletions flang/tools/bbc/bbc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,6 @@ static llvm::cl::opt<bool> enableOpenACC("fopenacc",
llvm::cl::desc("enable openacc"),
llvm::cl::init(false));

static llvm::cl::opt<bool> enablePolymorphic(
"polymorphic-type",
llvm::cl::desc("enable polymorphic type lowering (experimental)"),
llvm::cl::init(false));

static llvm::cl::opt<bool> enableNoPPCNativeVecElemOrder(
"fno-ppc-native-vector-element-order",
llvm::cl::desc("no PowerPC native vector element order."),
Expand Down Expand Up @@ -351,7 +346,6 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
std::string targetTriple = targetMachine.getTargetTriple().normalize();
// Use default lowering options for bbc.
Fortran::lower::LoweringOptions loweringOptions{};
loweringOptions.setPolymorphicTypeImpl(enablePolymorphic);
loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder);
loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);
std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ bool LibcxxStdSliceArraySummaryProvider(ValueObject &valobj, Stream &stream,
return false;
const size_t stride = ptr_sp->GetValueAsUnsigned(0);

stream.Printf("stride=%" PRIu64 " size=%" PRIu64, stride, size);
stream.Printf("stride=%zu size=%zu", stride, size);

return true;
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Changes to Interprocedural Optimizations
Changes to the AArch64 Backend
------------------------------

* Added support for Cortex-A78AE, Cortex-A520AE and Cortex-A720AE CPUs.

Changes to the AMDGPU Backend
-----------------------------

Expand Down
9 changes: 6 additions & 3 deletions llvm/include/llvm/Support/AMDHSAKernelDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@

// Sets bits for specified bit mask in specified destination.
#ifndef AMDHSA_BITS_SET
#define AMDHSA_BITS_SET(DST, MSK, VAL) \
DST &= ~MSK; \
DST |= ((VAL << MSK ## _SHIFT) & MSK)
#define AMDHSA_BITS_SET(DST, MSK, VAL) \
do { \
auto local = VAL; \
DST &= ~MSK; \
DST |= ((local << MSK##_SHIFT) & MSK); \
} while (0)
#endif // AMDHSA_BITS_SET

namespace llvm {
Expand Down
11 changes: 11 additions & 0 deletions llvm/include/llvm/TargetParser/AArch64TargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,11 @@ inline constexpr CpuInfo CpuInfos[] = {
{AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
{"cortex-a520ae", ARMV9_2A,
AArch64::ExtensionBitset(
{AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})},
{"cortex-a57", ARMV8A,
AArch64::ExtensionBitset(
{AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})},
Expand Down Expand Up @@ -621,6 +626,12 @@ inline constexpr CpuInfo CpuInfos[] = {
AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})},
{"cortex-a720ae", ARMV9_2A,
AArch64::ExtensionBitset({AArch64::AEK_SB, AArch64::AEK_SSBS,
AArch64::AEK_MTE, AArch64::AEK_FP16FML,
AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON,
AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})},
{"cortex-r82", ARMV8R, AArch64::ExtensionBitset({AArch64::AEK_LSE})},
{"cortex-x1", ARMV8_2A,
AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2,
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3972,10 +3972,16 @@ std::tuple<Value *, FPClassTest, FPClassTest>
llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
FPClassTest RHSClass, bool LookThroughSrc) {
assert(RHSClass != fcNone);
Value *Src = LHS;

if (Pred == FCmpInst::FCMP_TRUE)
return exactClass(Src, fcAllFlags);

if (Pred == FCmpInst::FCMP_FALSE)
return exactClass(Src, fcNone);

const FPClassTest OrigClass = RHSClass;

Value *Src = LHS;
const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
const bool IsNaN = (RHSClass & ~fcNan) == fcNone;
Expand All @@ -3994,12 +4000,6 @@ llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
if (Pred == FCmpInst::FCMP_UNO)
return exactClass(Src, fcNan);

if (Pred == FCmpInst::FCMP_TRUE)
return exactClass(Src, fcAllFlags);

if (Pred == FCmpInst::FCMP_FALSE)
return exactClass(Src, fcNone);

const bool IsFabs = LookThroughSrc && match(LHS, m_FAbs(m_Value(Src)));
if (IsFabs)
RHSClass = llvm::inverse_fabs(RHSClass);
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2820,6 +2820,23 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) {
return SDValue();
}

// Attempt to form avgflooru(A, B) from (A & B) + ((A ^ B) >> 1)
static SDValue combineFixedwidthToAVGFLOORU(SDNode *N, SelectionDAG &DAG) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDValue N0 = N->getOperand(0);
EVT VT = N0.getValueType();
SDLoc DL(N);
if (TLI.isOperationLegal(ISD::AVGFLOORU, VT)) {
SDValue A, B;
if (sd_match(N, m_Add(m_And(m_Value(A), m_Value(B)),
m_Srl(m_Xor(m_Deferred(A), m_Deferred(B)),
m_SpecificInt(1))))) {
return DAG.getNode(ISD::AVGFLOORU, DL, VT, A, B);
}
}
return SDValue();
}

SDValue DAGCombiner::visitADD(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
Expand All @@ -2835,6 +2852,10 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
if (SDValue V = foldAddSubOfSignBit(N, DAG))
return V;

// Try to match AVGFLOORU fixedwidth pattern
if (SDValue V = combineFixedwidthToAVGFLOORU(N, DAG))
return V;

// fold (a+b) -> (a|b) iff a and b share no bits.
if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) &&
DAG.haveNoCommonBitsSet(N0, N1))
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/IR/ConstantFold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1154,10 +1154,9 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2) {
GV->getType()->getAddressSpace()))
return ICmpInst::ICMP_UGT;
}
} else {
} else if (auto *CE1 = dyn_cast<ConstantExpr>(V1)) {
// Ok, the LHS is known to be a constantexpr. The RHS can be any of a
// constantexpr, a global, block address, or a simple constant.
ConstantExpr *CE1 = cast<ConstantExpr>(V1);
Constant *CE1Op0 = CE1->getOperand(0);

switch (CE1->getOpcode()) {
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/Target/AArch64/AArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,12 @@ def TuneA520 : SubtargetFeature<"a520", "ARMProcFamily", "CortexA520",
FeatureFuseAdrpAdd,
FeaturePostRAScheduler]>;

def TuneA520AE : SubtargetFeature<"a520ae", "ARMProcFamily", "CortexA520",
"Cortex-A520AE ARM processors", [
FeatureFuseAES,
FeatureFuseAdrpAdd,
FeaturePostRAScheduler]>;

def TuneA57 : SubtargetFeature<"a57", "ARMProcFamily", "CortexA57",
"Cortex-A57 ARM processors", [
FeatureFuseAES,
Expand Down Expand Up @@ -1001,6 +1007,17 @@ def TuneA720 : SubtargetFeature<"a720", "ARMProcFamily", "CortexA720",
FeatureEnableSelectOptimize,
FeaturePredictableSelectIsExpensive]>;

def TuneA720AE : SubtargetFeature<"a720ae", "ARMProcFamily", "CortexA720",
"Cortex-A720AE ARM processors", [
FeatureFuseAES,
FeaturePostRAScheduler,
FeatureCmpBccFusion,
FeatureAddrLSLFast,
FeatureALULSLFast,
FeatureFuseAdrpAdd,
FeatureEnableSelectOptimize,
FeaturePredictableSelectIsExpensive]>;

def TuneR82 : SubtargetFeature<"cortex-r82", "ARMProcFamily",
"CortexR82",
"Cortex-R82 ARM processors", [
Expand Down Expand Up @@ -1423,6 +1440,9 @@ def ProcessorFeatures {
list<SubtargetFeature> A520 = [HasV9_2aOps, FeaturePerfMon, FeatureAM,
FeatureMTE, FeatureETE, FeatureSVE2BitPerm,
FeatureFP16FML];
list<SubtargetFeature> A520AE = [HasV9_2aOps, FeaturePerfMon, FeatureAM,
FeatureMTE, FeatureETE, FeatureSVE2BitPerm,
FeatureFP16FML];
list<SubtargetFeature> A65 = [HasV8_2aOps, FeatureCrypto, FeatureFPARMv8,
FeatureNEON, FeatureFullFP16, FeatureDotProd,
FeatureRCPC, FeatureSSBS, FeatureRAS,
Expand Down Expand Up @@ -1456,6 +1476,9 @@ def ProcessorFeatures {
list<SubtargetFeature> A720 = [HasV9_2aOps, FeatureMTE, FeatureFP16FML,
FeatureTRBE, FeatureSVE2BitPerm, FeatureETE,
FeaturePerfMon, FeatureSPE, FeatureSPE_EEF];
list<SubtargetFeature> A720AE = [HasV9_2aOps, FeatureMTE, FeatureFP16FML,
FeatureTRBE, FeatureSVE2BitPerm, FeatureETE,
FeaturePerfMon, FeatureSPE, FeatureSPE_EEF];
list<SubtargetFeature> R82 = [HasV8_0rOps, FeaturePerfMon, FeatureFullFP16,
FeatureFP16FML, FeatureSSBS, FeaturePredRes,
FeatureSB, FeatureRDM, FeatureDotProd,
Expand Down Expand Up @@ -1598,6 +1621,8 @@ def : ProcessorModel<"cortex-a510", CortexA510Model, ProcessorFeatures.A510,
[TuneA510]>;
def : ProcessorModel<"cortex-a520", CortexA510Model, ProcessorFeatures.A520,
[TuneA520]>;
def : ProcessorModel<"cortex-a520ae", CortexA510Model, ProcessorFeatures.A520AE,
[TuneA520AE]>;
def : ProcessorModel<"cortex-a57", CortexA57Model, ProcessorFeatures.A53,
[TuneA57]>;
def : ProcessorModel<"cortex-a65", CortexA53Model, ProcessorFeatures.A65,
Expand Down Expand Up @@ -1628,6 +1653,8 @@ def : ProcessorModel<"cortex-a715", NeoverseN2Model, ProcessorFeatures.A715,
[TuneA715]>;
def : ProcessorModel<"cortex-a720", NeoverseN2Model, ProcessorFeatures.A720,
[TuneA720]>;
def : ProcessorModel<"cortex-a720ae", NeoverseN2Model, ProcessorFeatures.A720AE,
[TuneA720AE]>;
def : ProcessorModel<"cortex-r82", CortexA55Model, ProcessorFeatures.R82,
[TuneR82]>;
def : ProcessorModel<"cortex-x1", CortexA57Model, ProcessorFeatures.X1,
Expand Down
142 changes: 108 additions & 34 deletions llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/InstSimplifyFolder.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include "llvm/IR/IntrinsicsR600.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
Expand All @@ -64,10 +66,17 @@ static cl::opt<unsigned> PromoteAllocaToVectorLimit(
cl::desc("Maximum byte size to consider promote alloca to vector"),
cl::init(0));

static cl::opt<unsigned>
LoopUserWeight("promote-alloca-vector-loop-user-weight",
cl::desc("The bonus weight of users of allocas within loop "
"when sorting profitable allocas"),
cl::init(4));

// Shared implementation which can do both promotion to vector and to LDS.
class AMDGPUPromoteAllocaImpl {
private:
const TargetMachine &TM;
LoopInfo &LI;
Module *Mod = nullptr;
const DataLayout *DL = nullptr;

Expand Down Expand Up @@ -101,8 +110,11 @@ class AMDGPUPromoteAllocaImpl {
bool tryPromoteAllocaToVector(AllocaInst &I);
bool tryPromoteAllocaToLDS(AllocaInst &I, bool SufficientLDS);

void sortAllocasToPromote(SmallVectorImpl<AllocaInst *> &Allocas);

public:
AMDGPUPromoteAllocaImpl(TargetMachine &TM) : TM(TM) {
AMDGPUPromoteAllocaImpl(TargetMachine &TM, LoopInfo &LI) : TM(TM), LI(LI) {

const Triple &TT = TM.getTargetTriple();
IsAMDGCN = TT.getArch() == Triple::amdgcn;
IsAMDHSA = TT.getOS() == Triple::AMDHSA;
Expand All @@ -122,7 +134,9 @@ class AMDGPUPromoteAlloca : public FunctionPass {
if (skipFunction(F))
return false;
if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>())
return AMDGPUPromoteAllocaImpl(TPC->getTM<TargetMachine>())
return AMDGPUPromoteAllocaImpl(
TPC->getTM<TargetMachine>(),
getAnalysis<LoopInfoWrapperPass>().getLoopInfo())
.run(F, /*PromoteToLDS*/ true);
return false;
}
Expand All @@ -131,6 +145,7 @@ class AMDGPUPromoteAlloca : public FunctionPass {

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
FunctionPass::getAnalysisUsage(AU);
}
};
Expand All @@ -145,7 +160,9 @@ class AMDGPUPromoteAllocaToVector : public FunctionPass {
if (skipFunction(F))
return false;
if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>())
return AMDGPUPromoteAllocaImpl(TPC->getTM<TargetMachine>())
return AMDGPUPromoteAllocaImpl(
TPC->getTM<TargetMachine>(),
getAnalysis<LoopInfoWrapperPass>().getLoopInfo())
.run(F, /*PromoteToLDS*/ false);
return false;
}
Expand All @@ -156,6 +173,7 @@ class AMDGPUPromoteAllocaToVector : public FunctionPass {

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
FunctionPass::getAnalysisUsage(AU);
}
};
Expand Down Expand Up @@ -186,18 +204,23 @@ INITIALIZE_PASS_BEGIN(AMDGPUPromoteAlloca, DEBUG_TYPE,
// Move LDS uses from functions to kernels before promote alloca for accurate
// estimation of LDS available
INITIALIZE_PASS_DEPENDENCY(AMDGPULowerModuleLDSLegacy)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(AMDGPUPromoteAlloca, DEBUG_TYPE,
"AMDGPU promote alloca to vector or LDS", false, false)

INITIALIZE_PASS(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector",
"AMDGPU promote alloca to vector", false, false)
INITIALIZE_PASS_BEGIN(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector",
"AMDGPU promote alloca to vector", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector",
"AMDGPU promote alloca to vector", false, false)

char &llvm::AMDGPUPromoteAllocaID = AMDGPUPromoteAlloca::ID;
char &llvm::AMDGPUPromoteAllocaToVectorID = AMDGPUPromoteAllocaToVector::ID;

PreservedAnalyses AMDGPUPromoteAllocaPass::run(Function &F,
FunctionAnalysisManager &AM) {
bool Changed = AMDGPUPromoteAllocaImpl(TM).run(F, /*PromoteToLDS*/ true);
auto &LI = AM.getResult<LoopAnalysis>(F);
bool Changed = AMDGPUPromoteAllocaImpl(TM, LI).run(F, /*PromoteToLDS=*/true);
if (Changed) {
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
Expand All @@ -208,7 +231,8 @@ PreservedAnalyses AMDGPUPromoteAllocaPass::run(Function &F,

PreservedAnalyses
AMDGPUPromoteAllocaToVectorPass::run(Function &F, FunctionAnalysisManager &AM) {
bool Changed = AMDGPUPromoteAllocaImpl(TM).run(F, /*PromoteToLDS*/ false);
auto &LI = AM.getResult<LoopAnalysis>(F);
bool Changed = AMDGPUPromoteAllocaImpl(TM, LI).run(F, /*PromoteToLDS=*/false);
if (Changed) {
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
Expand All @@ -225,6 +249,55 @@ FunctionPass *llvm::createAMDGPUPromoteAllocaToVector() {
return new AMDGPUPromoteAllocaToVector();
}

static void collectAllocaUses(AllocaInst &Alloca,
SmallVectorImpl<Use *> &Uses) {
SmallVector<Instruction *, 4> WorkList({&Alloca});
while (!WorkList.empty()) {
auto *Cur = WorkList.pop_back_val();
for (auto &U : Cur->uses()) {
Uses.push_back(&U);

if (isa<GetElementPtrInst>(U.getUser()))
WorkList.push_back(cast<Instruction>(U.getUser()));
}
}
}

void AMDGPUPromoteAllocaImpl::sortAllocasToPromote(
SmallVectorImpl<AllocaInst *> &Allocas) {
DenseMap<AllocaInst *, unsigned> Scores;

for (auto *Alloca : Allocas) {
LLVM_DEBUG(dbgs() << "Scoring: " << *Alloca << "\n");
unsigned &Score = Scores[Alloca];
// Increment score by one for each user + a bonus for users within loops.
SmallVector<Use *, 8> Uses;
collectAllocaUses(*Alloca, Uses);
for (auto *U : Uses) {
Instruction *Inst = cast<Instruction>(U->getUser());
if (isa<GetElementPtrInst>(Inst))
continue;
unsigned UserScore =
1 + (LoopUserWeight * LI.getLoopDepth(Inst->getParent()));
LLVM_DEBUG(dbgs() << " [+" << UserScore << "]:\t" << *Inst << "\n");
Score += UserScore;
}
LLVM_DEBUG(dbgs() << " => Final Score:" << Score << "\n");
}

stable_sort(Allocas, [&](AllocaInst *A, AllocaInst *B) {
return Scores.at(A) > Scores.at(B);
});

// clang-format off
LLVM_DEBUG(
dbgs() << "Sorted Worklist:\n";
for (auto *A: Allocas)
dbgs() << " " << *A << "\n";
);
// clang-format on
}

bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) {
Mod = F.getParent();
DL = &Mod->getDataLayout();
Expand All @@ -237,6 +310,13 @@ bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) {

bool SufficientLDS = PromoteToLDS ? hasSufficientLocalMem(F) : false;

// Use up to 1/4 of available register budget for vectorization.
// FIXME: Increase the limit for whole function budgets? Perhaps x2?
unsigned VectorizationBudget =
(PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8
: (MaxVGPRs * 32)) /
4;

SmallVector<AllocaInst *, 16> Allocas;
for (Instruction &I : F.getEntryBlock()) {
if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
Expand All @@ -248,11 +328,27 @@ bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) {
}
}

sortAllocasToPromote(Allocas);

bool Changed = false;
for (AllocaInst *AI : Allocas) {
if (tryPromoteAllocaToVector(*AI))
const unsigned AllocaCost = DL->getTypeSizeInBits(AI->getAllocatedType());
if (AllocaCost > VectorizationBudget) {
LLVM_DEBUG(dbgs() << " Alloca too big for vectorization: " << *AI
<< "\n");
return false;
}

if (tryPromoteAllocaToVector(*AI)) {
Changed = true;
else if (PromoteToLDS && tryPromoteAllocaToLDS(*AI, SufficientLDS))
assert((VectorizationBudget - AllocaCost) < VectorizationBudget &&
"Underflow!");
VectorizationBudget -= AllocaCost;
LLVM_DEBUG(dbgs() << " Remaining vectorization budget:"
<< VectorizationBudget << "\n");
if (VectorizationBudget == 0)
break;
} else if (PromoteToLDS && tryPromoteAllocaToLDS(*AI, SufficientLDS))
Changed = true;
}

Expand Down Expand Up @@ -641,16 +737,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) {
ArrayTy->getNumElements());
}

// Use up to 1/4 of available register budget for vectorization.
unsigned Limit = PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8
: (MaxVGPRs * 32);

if (DL->getTypeSizeInBits(AllocaTy) * 4 > Limit) {
LLVM_DEBUG(dbgs() << " Alloca too big for vectorization with " << MaxVGPRs
<< " registers available\n");
return false;
}

// FIXME: There is no reason why we can't support larger arrays, we
// are just being conservative for now.
// FIXME: We also reject alloca's of the form [ 2 x [ 2 x i32 ]] or
Expand All @@ -671,7 +757,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) {
SmallVector<Instruction *> WorkList;
SmallVector<Instruction *> UsersToRemove;
SmallVector<Instruction *> DeferredInsts;
SmallVector<Use *, 8> Uses;
DenseMap<MemTransferInst *, MemTransferInfo> TransferInfo;

const auto RejectUser = [&](Instruction *Inst, Twine Msg) {
Expand All @@ -680,15 +765,14 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) {
return false;
};

for (Use &U : Alloca.uses())
Uses.push_back(&U);
SmallVector<Use *, 8> Uses;
collectAllocaUses(Alloca, Uses);

LLVM_DEBUG(dbgs() << " Attempting promotion to: " << *VectorTy << "\n");

Type *VecEltTy = VectorTy->getElementType();
unsigned ElementSize = DL->getTypeSizeInBits(VecEltTy) / 8;
while (!Uses.empty()) {
Use *U = Uses.pop_back_val();
for (auto *U : Uses) {
Instruction *Inst = cast<Instruction>(U->getUser());

if (Value *Ptr = getLoadStorePointerOperand(Inst)) {
Expand Down Expand Up @@ -724,14 +808,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) {
continue;
}

if (isa<BitCastInst>(Inst)) {
// Look through bitcasts.
for (Use &U : Inst->uses())
Uses.push_back(&U);
UsersToRemove.push_back(Inst);
continue;
}

if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
// If we can't compute a vector index from this GEP, then we can't
// promote this alloca to vector.
Expand All @@ -740,8 +816,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) {
return RejectUser(Inst, "cannot compute vector index for GEP");

GEPVectorIdx[GEP] = Index;
for (Use &U : Inst->uses())
Uses.push_back(&U);
UsersToRemove.push_back(Inst);
continue;
}
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,14 @@ class LoongArchOperand : public MCParsedAsmOperand {
}

bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
bool isImm64() const {
if (!isImm())
return false;
int64_t Imm;
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
}

/// Gets location of the first token of this operand.
SMLoc getStartLoc() const override { return StartLoc; }
Expand Down Expand Up @@ -1514,6 +1522,10 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a 32 bit immediate");
}
case Match_InvalidImm64: {
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a 64 bit immediate");
}
case Match_InvalidBareSymbol: {
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a bare symbol name");
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ def grlenimm : Operand<GRLenVT>;
def imm32 : Operand<GRLenVT> {
let ParserMatchClass = ImmAsmOperand<"", 32, "">;
}
def imm64 : Operand<i64> {
let ParserMatchClass = ImmAsmOperand<"", 64, "">;
}

def uimm1 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>{
let ParserMatchClass = UImmAsmOperand<1>;
Expand Down Expand Up @@ -2179,7 +2182,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
isAsmParserOnly = 1 in {
def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [],
"li.w", "$rd, $imm">;
def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [],
def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins imm64:$imm), [],
"li.d", "$rd, $imm">, Requires<[IsLA64]>;
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/TargetParser/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
.Case("0xd05", "cortex-a55")
.Case("0xd46", "cortex-a510")
.Case("0xd80", "cortex-a520")
.Case("0xd88", "cortex-a520ae")
.Case("0xd07", "cortex-a57")
.Case("0xd06", "cortex-a65")
.Case("0xd43", "cortex-a65ae")
Expand All @@ -235,6 +236,7 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
.Case("0xd47", "cortex-a710")
.Case("0xd4d", "cortex-a715")
.Case("0xd81", "cortex-a720")
.Case("0xd89", "cortex-a720ae")
.Case("0xd44", "cortex-x1")
.Case("0xd4c", "cortex-x1c")
.Case("0xd48", "cortex-x2")
Expand Down
Loading