Skip to content

Commit 1f8e487

Browse files
committed
[CSOptimizer] Prefer logical infix operator if it has smaller overload set
Infix logical operators are usually not overloaded and don't form disjunctions, but when they do, let's prefer them over other operators when they have fewer choices because it helps to split operator chains.
1 parent 65d9f5f commit 1f8e487

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

include/swift/AST/Identifier.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ class Identifier {
140140
return is("??");
141141
}
142142

143+
// Returns whether this is a standard infix logical operator,
144+
// such as '&&', '||'.
145+
bool isStandardInfixLogicalOperator() const { return is("&&") || is("||"); }
146+
143147
/// isOperatorStartCodePoint - Return true if the specified code point is a
144148
/// valid start of an operator.
145149
static bool isOperatorStartCodePoint(uint32_t C) {

lib/Sema/CSOptimizer.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ static bool isStandardComparisonOperator(Constraint *disjunction) {
251251
return false;
252252
}
253253

254+
static bool isStandardInfixLogicalOperator(Constraint *disjunction) {
255+
auto *choice = disjunction->getNestedConstraints()[0];
256+
if (auto *decl = getOverloadChoiceDecl(choice))
257+
return decl->isOperator() &&
258+
decl->getBaseIdentifier().isStandardInfixLogicalOperator();
259+
return false;
260+
}
261+
254262
static bool isOperatorNamed(Constraint *disjunction, StringRef name) {
255263
auto *choice = disjunction->getNestedConstraints()[0];
256264
if (auto *decl = getOverloadChoiceDecl(choice))
@@ -1856,6 +1864,16 @@ ConstraintSystem::selectDisjunction() {
18561864
bool isFirstOperator = isOperatorDisjunction(first);
18571865
bool isSecondOperator = isOperatorDisjunction(second);
18581866

1867+
// Infix logical operators are usually not overloaded and don't
1868+
// form disjunctions, but when they do, let's prefer them over
1869+
// other operators when they have fewer choices because it helps
1870+
// to split operator chains.
1871+
if (isFirstOperator && isSecondOperator) {
1872+
if (isStandardInfixLogicalOperator(first) !=
1873+
isStandardInfixLogicalOperator(second))
1874+
return firstActive < secondActive;
1875+
}
1876+
18591877
// Not all of the non-operator disjunctions are supported by the
18601878
// ranking algorithm, so to prevent eager selection of operators
18611879
// when nothing concrete is known about them, let's reset the score
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %scale-test --begin 1 --end 20 --step 1 --select NumLeafScopes %s
2+
// REQUIRES: asserts,no_asan
3+
4+
struct Predicate<T> : Equatable {}
5+
6+
func ||<T>(_: Predicate<T>, _: Predicate<T>) -> Predicate<T> {
7+
.init()
8+
}
9+
10+
func !=<Value, Operand>(_: Operand, _: Operand) -> Predicate<Value> where Operand : Equatable {
11+
.init()
12+
}
13+
14+
func !=<Value, Operand>(_: Operand, _: KeyPath<Value, Operand>) -> Predicate<Value> where Operand : Equatable {
15+
.init()
16+
}
17+
18+
func !=<Value, Operand>(_: KeyPath<Value, Operand>, _: Operand) -> Predicate<Value> where Operand : Equatable {
19+
.init()
20+
}
21+
22+
func !=<Value, Operand>(_: KeyPath<Value, Operand>, _: KeyPath<Value, Operand>) -> Predicate<Value> where Operand : Equatable {
23+
.init()
24+
}
25+
26+
enum Format : UInt, Equatable {
27+
case simple = 0
28+
}
29+
30+
struct Parameter {
31+
struct Buffers {
32+
struct Data {
33+
let format: Format
34+
}
35+
36+
let data: Data?
37+
}
38+
39+
var buffers: Buffers
40+
}
41+
42+
func test(arr: [Parameter]) {
43+
for p in arr {
44+
if (p.buffers.data != nil && p.buffers.data!.format != .simple) ||
45+
%for i in range(1, N):
46+
(p.buffers.data != nil && p.buffers.data!.format != .simple) ||
47+
%end
48+
(p.buffers.data != nil && p.buffers.data!.format != .simple) {
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)