Skip to content

Commit b490a2a

Browse files
authored
Merge pull request #21280 from DougGregor/simd-operator-type-check-perf-hack-5.0
[5.0] [Constraint solver] De-prioritize SIMD operators.
2 parents 050c1db + f20b7b0 commit b490a2a

File tree

4 files changed

+132
-0
lines changed

4 files changed

+132
-0
lines changed

lib/Sema/CSStep.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,27 @@ bool DisjunctionStep::shouldStopAt(const DisjunctionChoice &choice) const {
490490
shortCircuitDisjunctionAt(choice, lastChoice));
491491
}
492492

493+
bool swift::isSIMDOperator(ValueDecl *value) {
494+
if (!value)
495+
return false;
496+
497+
auto func = dyn_cast<FuncDecl>(value);
498+
if (!func)
499+
return false;
500+
501+
if (!func->isOperator())
502+
return false;
503+
504+
auto nominal = func->getDeclContext()->getSelfNominalTypeDecl();
505+
if (!nominal)
506+
return false;
507+
508+
if (nominal->getName().empty())
509+
return false;
510+
511+
return nominal->getName().str().startswith_lower("simd");
512+
}
513+
493514
bool DisjunctionStep::shortCircuitDisjunctionAt(
494515
Constraint *currentChoice, Constraint *lastSuccessfulChoice) const {
495516
auto &ctx = CS.getASTContext();
@@ -535,6 +556,16 @@ bool DisjunctionStep::shortCircuitDisjunctionAt(
535556
if (currentChoice->getKind() == ConstraintKind::CheckedCast)
536557
return true;
537558

559+
// If we have an operator from the SIMDOperators module, and the prior
560+
// choice was not from the SIMDOperators module, we're done.
561+
if (currentChoice->getKind() == ConstraintKind::BindOverload &&
562+
isSIMDOperator(currentChoice->getOverloadChoice().getDecl()) &&
563+
lastSuccessfulChoice->getKind() == ConstraintKind::BindOverload &&
564+
!isSIMDOperator(lastSuccessfulChoice->getOverloadChoice().getDecl()) &&
565+
!ctx.LangOpts.SolverEnableOperatorDesignatedTypes) {
566+
return true;
567+
}
568+
538569
return false;
539570
}
540571

lib/Sema/ConstraintSystem.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,40 @@ static void tryOptimizeGenericDisjunction(ConstraintSystem &cs,
14431443
}
14441444
}
14451445

1446+
/// If there are any SIMD operators in the overload set, partition the set so
1447+
/// that the SIMD operators come at the end.
1448+
static ArrayRef<OverloadChoice> partitionSIMDOperators(
1449+
ArrayRef<OverloadChoice> choices,
1450+
SmallVectorImpl<OverloadChoice> &scratch) {
1451+
// If the first element isn't an operator, none of them are.
1452+
if (!choices[0].isDecl() ||
1453+
!isa<FuncDecl>(choices[0].getDecl()) ||
1454+
!cast<FuncDecl>(choices[0].getDecl())->isOperator() ||
1455+
choices[0].getDecl()->getASTContext().LangOpts
1456+
.SolverEnableOperatorDesignatedTypes)
1457+
return choices;
1458+
1459+
// Check whether we have any SIMD operators.
1460+
bool foundSIMDOperator = false;
1461+
for (const auto &choice : choices) {
1462+
if (isSIMDOperator(choice.getDecl())) {
1463+
foundSIMDOperator = true;
1464+
break;
1465+
}
1466+
}
1467+
1468+
if (!foundSIMDOperator)
1469+
return choices;
1470+
1471+
scratch.assign(choices.begin(), choices.end());
1472+
std::stable_partition(scratch.begin(), scratch.end(),
1473+
[](const OverloadChoice &choice) {
1474+
return !isSIMDOperator(choice.getDecl());
1475+
});
1476+
1477+
return scratch;
1478+
}
1479+
14461480
void ConstraintSystem::addOverloadSet(Type boundType,
14471481
ArrayRef<OverloadChoice> choices,
14481482
DeclContext *useDC,
@@ -1459,6 +1493,9 @@ void ConstraintSystem::addOverloadSet(Type boundType,
14591493

14601494
tryOptimizeGenericDisjunction(*this, choices, favoredChoice);
14611495

1496+
SmallVector<OverloadChoice, 4> scratchChoices;
1497+
choices = partitionSIMDOperators(choices, scratchChoices);
1498+
14621499
SmallVector<Constraint *, 4> overloads;
14631500

14641501
// As we do for other favored constraints, if a favored overload has been

lib/Sema/ConstraintSystem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3830,6 +3830,9 @@ bool exprNeedsParensOutsideFollowingOperator(
38303830
TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr,
38313831
PrecedenceGroupDecl *followingPG);
38323832

3833+
/// Determine whether this is a SIMD operator.
3834+
bool isSIMDOperator(ValueDecl *value);
3835+
38333836
} // end namespace swift
38343837

38353838
#endif // LLVM_SWIFT_SEMA_CONSTRAINT_SYSTEM_H
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// REQUIRES: OS=macosx
3+
4+
import simd
5+
import CoreGraphics
6+
import Foundation
7+
8+
class SomeView {
9+
func layoutSubviews() {
10+
let descriptionTextViewFrame = CGRect.zero
11+
let availableBounds = CGRect()
12+
let descriptionLabelProperties = SomeView.descriptionTextViewLabelProperties()
13+
let textSize = descriptionTextView.sizeThatFits(availableBounds.size)
14+
let textInset = descriptionTextView.textInset(forBounds: CGRect(origin: .zero, size: textSize))
15+
let descriptionTextBaselineOffset: CGFloat = CGFloat()
16+
let displayScale: CGFloat = CGFloat()
17+
let _ = (descriptionTextViewFrame.height
18+
+ (-descriptionTextView.lastBaselineOffsetFromBottom - textInset.bottom + descriptionLabelProperties.lastBaselineOffsetFromBottom)
19+
+ (-descriptionTextView.firstBaselineOffsetFromTop - textInset.top + descriptionTextBaselineOffset).ceilingValue(scale: displayScale)
20+
)
21+
}
22+
23+
static func descriptionTextViewLabelProperties() -> FontDescriptorBaselineProperties {
24+
fatalError()
25+
}
26+
27+
lazy var descriptionTextView: SomeOtherView = SomeOtherView()
28+
}
29+
30+
class SomeOtherView {
31+
init() { }
32+
func sizeThatFits(_ size: CGSize) -> CGSize { return size }
33+
}
34+
35+
36+
struct FontDescriptorBaselineProperties {
37+
// let fontDescriptor: MPUFontDescriptor
38+
let defaultFirstBaselineOffsetFromTop: CGFloat
39+
let defaultLastBaselineOffsetFromBottom: CGFloat
40+
var firstBaselineOffsetFromTop: CGFloat { fatalError() }
41+
var lastBaselineOffsetFromBottom: CGFloat {
42+
fatalError()
43+
}
44+
}
45+
46+
struct EdgeInsets {
47+
var top: CGFloat
48+
var bottom: CGFloat
49+
}
50+
51+
extension SomeOtherView {
52+
func textInset(forBounds bounds: CGRect) -> EdgeInsets { fatalError() }
53+
var firstBaselineOffsetFromTop: CGFloat { fatalError() }
54+
var lastBaselineOffsetFromBottom: CGFloat {
55+
fatalError()
56+
}
57+
}
58+
59+
extension CGFloat {
60+
public func ceilingValue(scale: CGFloat) -> CGFloat { fatalError() }
61+
}

0 commit comments

Comments
 (0)