[flang-commits] [clang] [flang] [Flang] Repair intrinsic CUBLAS USE association (PR #217455)
via flang-commits
flang-commits at lists.llvm.org
Fri Aug 21 02:50:13 PDT 2026
================
@@ -4230,6 +4230,98 @@ static bool CheckCompatibleDistinctUltimates(SemanticsContext &context,
return true; // don't try to merge generics (or whatever)
}
+static bool AreSameProcedureForUseAssociation(
+ SemanticsContext &context, const Symbol &p1, const Symbol &p2) {
+ const Symbol &ultimate1{p1.GetUltimate()};
+ const Symbol &ultimate2{p2.GetUltimate()};
+ if (&ultimate1 == &ultimate2) {
+ return true;
+ } else if (ultimate1.name() != ultimate2.name()) {
+ return false;
+ } else if (ultimate1.attrs().test(Attr::INTRINSIC) ||
+ ultimate2.attrs().test(Attr::INTRINSIC)) {
+ return ultimate1.attrs().test(Attr::INTRINSIC) &&
+ ultimate2.attrs().test(Attr::INTRINSIC);
+ }
+ if (!IsProcedure(ultimate1) || IsPointer(ultimate1) ||
+ !IsProcedure(ultimate2) || IsPointer(ultimate2) ||
+ ClassifyProcedure(ultimate1) != ClassifyProcedure(ultimate2)) {
+ return false;
+ }
+ auto classification{ClassifyProcedure(ultimate1)};
+ if (classification == ProcedureDefinitionClass::Module) {
+ return AreSameModuleSymbol(ultimate1, ultimate2);
+ }
+ if (classification != ProcedureDefinitionClass::External) {
+ return false;
+ }
+ const auto *subp1{ultimate1.detailsIf<SubprogramDetails>()};
+ const auto *subp2{ultimate2.detailsIf<SubprogramDetails>()};
+ if (!subp1 || !subp1->isInterface() || !subp2 || !subp2->isInterface()) {
+ return false;
+ }
+ auto chars1{evaluate::characteristics::Procedure::Characterize(
+ ultimate1, context.foldingContext())};
+ auto chars2{evaluate::characteristics::Procedure::Characterize(
+ ultimate2, context.foldingContext())};
+ return chars1 && chars2 && *chars1 == *chars2;
+}
+
+static bool HasCUDADummyDataAttribute(const Symbol &procedure) {
+ if (const auto *subp{
+ procedure.GetUltimate().detailsIf<SubprogramDetails>()}) {
+ for (const Symbol *dummy : subp->dummyArgs()) {
+ if (dummy && GetCUDADataAttr(dummy)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+struct IntrinsicModuleUseAssociationRule {
+ const char *moduleName;
+ const char *genericName;
+ bool (*matches)(SemanticsContext &, const GenericDetails &, const Symbol &);
+};
+
+static bool MatchesCublasZgemm(SemanticsContext &context,
+ const GenericDetails &generic, const Symbol &other) {
+ const Symbol *specific{generic.specific()};
+ if (!specific ||
+ !AreSameProcedureForUseAssociation(context, *specific, other)) {
+ return false;
+ }
+ bool containsSpecific{false};
+ bool hasCUDAOverload{false};
+ for (const Symbol &candidate : generic.specificProcs()) {
+ containsSpecific |= &candidate.GetUltimate() == &specific->GetUltimate();
+ hasCUDAOverload |= HasCUDADummyDataAttribute(candidate);
+ }
+ return containsSpecific && hasCUDAOverload;
+}
+
+static const IntrinsicModuleUseAssociationRule *
+FindIntrinsicModuleUseAssociationRule(
+ SemanticsContext &context, const Symbol &generic, const Symbol &other) {
----------------
mleair wrote:
I suggest adding a comment here for the table below that explains its purpose and lets the developer know that it can be used in the future for adding more intrinsic module generic entries that should take precedence over an equivalent external interface during USE association. Maybe that comment can be:
https://github.com/llvm/llvm-project/pull/217455
More information about the flang-commits
mailing list