Skip to content

Commit aa50628

Browse files
authored
Merge pull request #21231 from DougGregor/simd-operator-type-check-perf-hack
[Constraint solver] De-prioritize SIMD operators.
2 parents 0625081 + 052d4c1 commit aa50628

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-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
@@ -3829,6 +3829,9 @@ bool exprNeedsParensOutsideFollowingOperator(
38293829
TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr,
38303830
PrecedenceGroupDecl *followingPG);
38313831

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

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

0 commit comments

Comments
 (0)