@@ -34,6 +34,19 @@ using namespace constraints;
34
34
35
35
namespace {
36
36
37
+ struct DisjunctionInfo {
38
+ // / The score of the disjunction is the highest score from its choices.
39
+ // / If the score is nullopt it means that the disjunction is not optimizable.
40
+ std::optional<double > Score;
41
+ // / The highest scoring choices that could be favored when disjunction
42
+ // / is attempted.
43
+ llvm::TinyPtrVector<Constraint *> FavoredChoices;
44
+
45
+ DisjunctionInfo () = default ;
46
+ DisjunctionInfo (double score, ArrayRef<Constraint *> favoredChoices = {})
47
+ : Score(score), FavoredChoices(favoredChoices) {}
48
+ };
49
+
37
50
// TODO: both `isIntegerType` and `isFloatType` should be available on Type
38
51
// as `isStdlib{Integer, Float}Type`.
39
52
@@ -246,16 +259,30 @@ static void findFavoredChoicesBasedOnArity(
246
259
// / favored choices in the current context.
247
260
static void determineBestChoicesInContext (
248
261
ConstraintSystem &cs, SmallVectorImpl<Constraint *> &disjunctions,
249
- llvm::DenseMap<Constraint *,
250
- std::pair<double , llvm::TinyPtrVector<Constraint *>>>
251
- &favorings) {
262
+ llvm::DenseMap<Constraint *, DisjunctionInfo> &result) {
252
263
double bestOverallScore = 0.0 ;
253
- // Tops scores across all of the disjunctions.
254
- llvm::DenseMap<Constraint *, double > disjunctionScores;
255
- llvm::DenseMap<Constraint *, llvm::TinyPtrVector<Constraint *>>
256
- favoredChoicesPerDisjunction;
264
+
265
+ auto recordResult = [&bestOverallScore, &result](Constraint *disjunction,
266
+ DisjunctionInfo &&info) {
267
+ bestOverallScore = std::max (bestOverallScore, info.Score .value_or (0 ));
268
+ result.try_emplace (disjunction, info);
269
+ };
257
270
258
271
for (auto *disjunction : disjunctions) {
272
+ // If this is a compiler synthesized disjunction, mark it as supported
273
+ // and record all of the previously favored choices. Such disjunctions
274
+ // include - explicit coercions, IUO references,injected implicit
275
+ // initializers for CGFloat<->Double conversions and restrictions with
276
+ // multiple choices.
277
+ if (disjunction->countFavoredNestedConstraints () > 0 ) {
278
+ DisjunctionInfo info (/* score=*/ 2.0 );
279
+ llvm::copy_if (disjunction->getNestedConstraints (),
280
+ std::back_inserter (info.FavoredChoices ),
281
+ [](Constraint *choice) { return choice->isFavored (); });
282
+ recordResult (disjunction, std::move (info));
283
+ continue ;
284
+ }
285
+
259
286
auto applicableFn =
260
287
getApplicableFnConstraint (cs.getConstraintGraph (), disjunction);
261
288
@@ -282,14 +309,14 @@ static void determineBestChoicesInContext(
282
309
// of `OverloadedDeclRef` calls were favored purely
283
310
// based on arity of arguments and parameters matching.
284
311
{
285
- findFavoredChoicesBasedOnArity (
286
- cs, disjunction, argumentList, [&](Constraint *choice) {
287
- favoredChoicesPerDisjunction[disjunction]. push_back ( choice);
288
- } );
289
-
290
- if (!favoredChoicesPerDisjunction[disjunction]. empty ()) {
291
- disjunctionScores[disjunction] = 0.01 ;
292
- bestOverallScore = std::max (bestOverallScore, 0.01 );
312
+ llvm::TinyPtrVector<Constraint *> favoredChoices;
313
+ findFavoredChoicesBasedOnArity ( cs, disjunction, argumentList,
314
+ [&favoredChoices](Constraint * choice) {
315
+ favoredChoices. push_back (choice );
316
+ });
317
+
318
+ if (!favoredChoices. empty ()) {
319
+ recordResult (disjunction, { /* score= */ 0.01 , favoredChoices} );
293
320
continue ;
294
321
}
295
322
}
@@ -894,17 +921,16 @@ static void determineBestChoicesInContext(
894
921
<< " with score " << bestScore << " \n " ;
895
922
}
896
923
897
- // No matching overload choices to favor.
898
- if (bestScore == 0.0 )
899
- continue ;
900
-
901
924
bestOverallScore = std::max (bestOverallScore, bestScore);
902
925
903
- disjunctionScores[disjunction] = bestScore;
926
+ DisjunctionInfo info (/* score=*/ bestScore);
927
+
904
928
for (const auto &choice : favoredChoices) {
905
929
if (choice.second == bestScore)
906
- favoredChoicesPerDisjunction[disjunction] .push_back (choice.first );
930
+ info. FavoredChoices .push_back (choice.first );
907
931
}
932
+
933
+ recordResult (disjunction, std::move (info));
908
934
}
909
935
910
936
if (cs.isDebugMode () && bestOverallScore > 0 ) {
@@ -935,14 +961,15 @@ static void determineBestChoicesInContext(
935
961
getLogger (/* extraIndent=*/ 4 )
936
962
<< " Best overall score = " << bestOverallScore << ' \n ' ;
937
963
938
- for (const auto &entry : disjunctionScores) {
964
+ for (auto *disjunction : disjunctions) {
965
+ auto &entry = result[disjunction];
939
966
getLogger (/* extraIndent=*/ 4 )
940
967
<< " [Disjunction '"
941
- << entry. first ->getNestedConstraints ()[0 ]->getFirstType ()->getString (
968
+ << disjunction ->getNestedConstraints ()[0 ]->getFirstType ()->getString (
942
969
PO)
943
- << " ' with score = " << entry.second << ' \n ' ;
970
+ << " ' with score = " << entry.Score . value_or ( 0 ) << ' \n ' ;
944
971
945
- for (const auto *choice : favoredChoicesPerDisjunction[ entry.first ] ) {
972
+ for (const auto *choice : entry.FavoredChoices ) {
946
973
auto &log = getLogger (/* extraIndent=*/ 6 );
947
974
948
975
log << " - " ;
@@ -955,16 +982,6 @@ static void determineBestChoicesInContext(
955
982
956
983
getLogger () << " )\n " ;
957
984
}
958
-
959
- if (bestOverallScore == 0 )
960
- return ;
961
-
962
- for (auto &entry : disjunctionScores) {
963
- TinyPtrVector<Constraint *> favoredChoices;
964
- for (auto *choice : favoredChoicesPerDisjunction[entry.first ])
965
- favoredChoices.push_back (choice);
966
- favorings[entry.first ] = std::make_pair (entry.second , favoredChoices);
967
- }
968
985
}
969
986
970
987
// Attempt to find a disjunction of bind constraints where all options
@@ -1036,9 +1053,7 @@ ConstraintSystem::selectDisjunction() {
1036
1053
if (auto *disjunction = selectBestBindingDisjunction (*this , disjunctions))
1037
1054
return std::make_pair (disjunction, llvm::TinyPtrVector<Constraint *>());
1038
1055
1039
- llvm::DenseMap<Constraint *,
1040
- std::pair</* bestScore=*/ double , llvm::TinyPtrVector<Constraint *>>>
1041
- favorings;
1056
+ llvm::DenseMap<Constraint *, DisjunctionInfo> favorings;
1042
1057
determineBestChoicesInContext (*this , disjunctions, favorings);
1043
1058
1044
1059
// Pick the disjunction with the smallest number of favored, then active
@@ -1052,23 +1067,16 @@ ConstraintSystem::selectDisjunction() {
1052
1067
auto &[firstScore, firstFavoredChoices] = favorings[first];
1053
1068
auto &[secondScore, secondFavoredChoices] = favorings[second];
1054
1069
1055
- bool isFirstSupported = isSupportedDisjunction (first);
1056
- bool isSecondSupported = isSupportedDisjunction (second);
1057
-
1058
1070
// Rank based on scores only if both disjunctions are supported.
1059
- if (isFirstSupported && isSecondSupported ) {
1071
+ if (firstScore && secondScore ) {
1060
1072
// If both disjunctions have the same score they should be ranked
1061
1073
// based on number of favored/active choices.
1062
- if (firstScore != secondScore)
1063
- return firstScore > secondScore;
1074
+ if (* firstScore != * secondScore)
1075
+ return * firstScore > * secondScore;
1064
1076
}
1065
1077
1066
- unsigned numFirstFavored = isFirstSupported
1067
- ? firstFavoredChoices.size ()
1068
- : first->countFavoredNestedConstraints ();
1069
- unsigned numSecondFavored =
1070
- isSecondSupported ? secondFavoredChoices.size ()
1071
- : second->countFavoredNestedConstraints ();
1078
+ unsigned numFirstFavored = firstFavoredChoices.size ();
1079
+ unsigned numSecondFavored = secondFavoredChoices.size ();
1072
1080
1073
1081
if (numFirstFavored == numSecondFavored) {
1074
1082
if (firstActive != secondActive)
@@ -1082,7 +1090,8 @@ ConstraintSystem::selectDisjunction() {
1082
1090
});
1083
1091
1084
1092
if (bestDisjunction != disjunctions.end ())
1085
- return std::make_pair (*bestDisjunction, favorings[*bestDisjunction].second );
1093
+ return std::make_pair (*bestDisjunction,
1094
+ favorings[*bestDisjunction].FavoredChoices );
1086
1095
1087
1096
return std::nullopt;
1088
1097
}
0 commit comments