mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
stdlib: remove bitwise operations on Bool
Bitwise operations on Bool are redundant with other logic operations that stdlib already provides. The only reason to have them was to avoid branching in the short-circuiting && and ||. rdar://19340952 Surprisingly, replacing & and | in the standard library with && and || brought performance improvements and no significant performance regressions: RecursiveOwnedParameter 1.14 SelectionSort 1.19 Swift SVN r24674
This commit is contained in:
@@ -64,27 +64,6 @@ extension Bool : Printable {
|
|||||||
public // COMPILER_INTRINSIC
|
public // COMPILER_INTRINSIC
|
||||||
func _getBool(v: Builtin.Int1) -> Bool { return Bool(v) }
|
func _getBool(v: Builtin.Int1) -> Bool { return Bool(v) }
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Standard Operators
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Unary bitwise complement.
|
|
||||||
@transparent
|
|
||||||
public prefix func ~(a: Bool) -> Bool {
|
|
||||||
return a ^ true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unary logical complement.
|
|
||||||
@transparent
|
|
||||||
public prefix func !(a: Bool) -> Bool {
|
|
||||||
return ~a
|
|
||||||
}
|
|
||||||
|
|
||||||
@transparent
|
|
||||||
public func ==(lhs: Bool, rhs: Bool) -> Bool {
|
|
||||||
return Bool(Builtin.cmp_eq_Int1(lhs.value, rhs.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
@transparent
|
@transparent
|
||||||
extension Bool : Equatable, Hashable {
|
extension Bool : Equatable, Hashable {
|
||||||
/// The hash value.
|
/// The hash value.
|
||||||
@@ -99,36 +78,64 @@ extension Bool : Equatable, Hashable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Operators
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Unary logical complement.
|
||||||
|
@transparent
|
||||||
|
public prefix func !(a: Bool) -> Bool {
|
||||||
|
return Bool(Builtin.xor_Int1(a.value, true.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
@transparent
|
||||||
|
public func ==(lhs: Bool, rhs: Bool) -> Bool {
|
||||||
|
return Bool(Builtin.cmp_eq_Int1(lhs.value, rhs.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Unavailable Operators
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Unary bitwise complement.
|
||||||
|
@availability(*, unavailable, message="use the '!' operator instead")
|
||||||
|
public prefix func ~(a: Bool) -> Bool {
|
||||||
|
_preconditionFailure("unavailable function can not be called")
|
||||||
|
}
|
||||||
|
|
||||||
// Bitwise 'and'.
|
// Bitwise 'and'.
|
||||||
@transparent public func & (lhs: Bool, rhs: Bool) -> Bool {
|
@availability(*, unavailable, message="use the '&&' operator instead")
|
||||||
return Bool(Builtin.and_Int1(lhs.value, rhs.value))
|
public func & (lhs: Bool, rhs: Bool) -> Bool {
|
||||||
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bitwise 'xor'.
|
// Bitwise 'xor'.
|
||||||
@transparent public func ^ (lhs: Bool, rhs: Bool) -> Bool {
|
@availability(*, unavailable, message="use the '!=' operator instead")
|
||||||
return Bool(Builtin.xor_Int1(lhs.value, rhs.value))
|
public func ^ (lhs: Bool, rhs: Bool) -> Bool {
|
||||||
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bitwise 'or'.
|
// Bitwise 'or'.
|
||||||
@transparent public func | (lhs: Bool, rhs: Bool) -> Bool {
|
@availability(*, unavailable, message="use the '||' operator instead")
|
||||||
return Bool(Builtin.or_Int1(lhs.value, rhs.value))
|
public func | (lhs: Bool, rhs: Bool) -> Bool {
|
||||||
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compound assignment (with bitwise and)
|
// Compound assignment (with bitwise and)
|
||||||
@transparent
|
@availability(*, unavailable, message="use the '&&' operator instead")
|
||||||
public func &= (inout lhs: Bool, rhs: Bool) {
|
public func &= (inout lhs: Bool, rhs: Bool) {
|
||||||
lhs = lhs & rhs
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compound assignment (with bitwise or)
|
// Compound assignment (with bitwise or)
|
||||||
@transparent
|
@availability(*, unavailable, message="use the '||' operator instead")
|
||||||
public func |= (inout lhs: Bool, rhs: Bool) {
|
public func |= (inout lhs: Bool, rhs: Bool) {
|
||||||
lhs = lhs | rhs
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compound assignment (with bitwise xor)
|
// Compound assignment (with bitwise xor)
|
||||||
@transparent
|
@availability(*, unavailable, message="use the '!=' operator instead")
|
||||||
public func ^= (inout lhs: Bool, rhs: Bool) {
|
public func ^= (inout lhs: Bool, rhs: Bool) {
|
||||||
lhs = lhs ^ rhs
|
_preconditionFailure("unavailable function can not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ public struct _ContiguousArrayBuffer<T> : _ArrayBufferType {
|
|||||||
/// Note that this is better than folding hasStorage in to
|
/// Note that this is better than folding hasStorage in to
|
||||||
/// the return from this function, as this implementation generates
|
/// the return from this function, as this implementation generates
|
||||||
/// no shortcircuiting blocks.
|
/// no shortcircuiting blocks.
|
||||||
return (index >= 0) & (index < __bufferPointer.value.count)
|
return (index >= 0) && (index < __bufferPointer.value.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How many elements the buffer can store without reallocation
|
/// How many elements the buffer can store without reallocation
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
|
|||||||
public func ${op}(lhs: ${Self}, rhs: ${Self}) -> ${Self} {
|
public func ${op}(lhs: ${Self}, rhs: ${Self}) -> ${Self} {
|
||||||
Builtin.condfail((rhs == 0).value)
|
Builtin.condfail((rhs == 0).value)
|
||||||
% if signed:
|
% if signed:
|
||||||
Builtin.condfail(((lhs == ${Self}.min) & (rhs == -1)).value)
|
Builtin.condfail(((lhs == ${Self}.min) && (rhs == -1)).value)
|
||||||
% end
|
% end
|
||||||
// FIXME: currently doesn't detect overflow -- blocked by:
|
// FIXME: currently doesn't detect overflow -- blocked by:
|
||||||
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
|
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ import SwiftShims
|
|||||||
/// ≤ index ≤ count`
|
/// ≤ index ≤ count`
|
||||||
@transparent
|
@transparent
|
||||||
internal func _isValidArrayIndex(index: Int, count: Int) -> Bool {
|
internal func _isValidArrayIndex(index: Int, count: Int) -> Bool {
|
||||||
return (index >= 0) & (index <= count)
|
return (index >= 0) && (index <= count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true iff the given `index` is valid for subscripting, i.e.
|
/// Return true iff the given `index` is valid for subscripting, i.e.
|
||||||
/// `0 ≤ index < count`
|
/// `0 ≤ index < count`
|
||||||
@transparent
|
@transparent
|
||||||
internal func _isValidArraySubscript(index: Int, count: Int) -> Bool {
|
internal func _isValidArraySubscript(index: Int, count: Int) -> Bool {
|
||||||
return (index >= 0) & (index < count)
|
return (index >= 0) && (index < count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `NSArray` with Swift-native reference counting and contiguous
|
/// An `NSArray` with Swift-native reference counting and contiguous
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public struct _UnitTestArrayBuffer<T> : _ArrayBufferType {
|
|||||||
/// the return from this function, as this implementation generates
|
/// the return from this function, as this implementation generates
|
||||||
/// no shortcircuiting blocks.
|
/// no shortcircuiting blocks.
|
||||||
_precondition(_base.hasStorage, "Cannot index empty buffer")
|
_precondition(_base.hasStorage, "Cannot index empty buffer")
|
||||||
return (index >= 0) & (index < _base.value.count)
|
return (index >= 0) && (index < _base.value.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How many elements the buffer can store without reallocation
|
/// How many elements the buffer can store without reallocation
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ public func expectGE(
|
|||||||
public func expectType<T>(_: T.Type, inout x: T) {}
|
public func expectType<T>(_: T.Type, inout x: T) {}
|
||||||
|
|
||||||
public func isSequenceType<X : SequenceType>(x: X) -> X { return x }
|
public func isSequenceType<X : SequenceType>(x: X) -> X { return x }
|
||||||
|
public func expectIsBooleanType<X : BooleanType>(inout x: X) -> X { return x }
|
||||||
|
|
||||||
public struct AssertionResult : Printable, BooleanType {
|
public struct AssertionResult : Printable, BooleanType {
|
||||||
init(isPass: Bool) {
|
init(isPass: Bool) {
|
||||||
|
|||||||
@@ -991,7 +991,7 @@ Reflection.test("CustomMirror") {
|
|||||||
// Check the ObjectIdentifier created is stable
|
// Check the ObjectIdentifier created is stable
|
||||||
expectTrue(
|
expectTrue(
|
||||||
(ObjectIdentifier(a) < ObjectIdentifier(b))
|
(ObjectIdentifier(a) < ObjectIdentifier(b))
|
||||||
^ (ObjectIdentifier(a) > ObjectIdentifier(b)))
|
!= (ObjectIdentifier(a) > ObjectIdentifier(b)))
|
||||||
expectFalse(
|
expectFalse(
|
||||||
ObjectIdentifier(a) >= ObjectIdentifier(b)
|
ObjectIdentifier(a) >= ObjectIdentifier(b)
|
||||||
&& ObjectIdentifier(a) <= ObjectIdentifier(b))
|
&& ObjectIdentifier(a) <= ObjectIdentifier(b))
|
||||||
|
|||||||
@@ -445,17 +445,6 @@ func testInOut(inout arg: Int) {
|
|||||||
takesExplicitInt(5) // expected-error {{cannot invoke 'takesExplicitInt' with an argument list of type '(Int)'}} expected-note{{expected an argument list of type '(inout Int)'}}
|
takesExplicitInt(5) // expected-error {{cannot invoke 'takesExplicitInt' with an argument list of type '(Int)'}} expected-note{{expected an argument list of type '(inout Int)'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Bool operators
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
func boolTest(a: Bool, b: Bool) {
|
|
||||||
var t1 = a != b
|
|
||||||
var t2 = a == b
|
|
||||||
var t3 = !a
|
|
||||||
var t4 = ~a
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Conversions
|
// Conversions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
12
validation-test/stdlib/BoolDiagnostics.swift
Normal file
12
validation-test/stdlib/BoolDiagnostics.swift
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// RUN: %target-parse-verify-swift
|
||||||
|
|
||||||
|
func test_removedOperators(a: Bool, b: Bool) {
|
||||||
|
var t1 = ~a // expected-error {{'~' is unavailable: use the '!' operator instead}}
|
||||||
|
var t2 = a & b // expected-error {{'&' is unavailable: use the '&&' operator instead}}
|
||||||
|
var t3 = a | b // expected-error {{'|' is unavailable: use the '||' operator instead}}
|
||||||
|
var t4 = a ^ b // expected-error {{'^' is unavailable: use the '!=' operator instead}}
|
||||||
|
t4 &= a // expected-error {{'&=' is unavailable: use the '&&' operator instead}}
|
||||||
|
t4 |= a // expected-error {{'|=' is unavailable: use the '||' operator instead}}
|
||||||
|
t4 ^= a // expected-error {{'^=' is unavailable: use the '!=' operator instead}}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -267,5 +267,100 @@ _UnimplementedError()
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
var BoolTestSuite = TestSuite("Bool")
|
||||||
|
|
||||||
|
BoolTestSuite.test("literals") {
|
||||||
|
if true {
|
||||||
|
var v = false
|
||||||
|
expectType(Bool.self, &v)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
var v = true
|
||||||
|
expectType(Bool.self, &v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("init()") {
|
||||||
|
let v = Bool()
|
||||||
|
expectFalse(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Booleanish : BooleanType {
|
||||||
|
let boolValue: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("init<T : BooleanType>(_:)") {
|
||||||
|
if true {
|
||||||
|
let v = Bool(Booleanish(boolValue: false))
|
||||||
|
expectFalse(v)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
let v = Bool(Booleanish(boolValue: true))
|
||||||
|
expectTrue(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("BooleanType") {
|
||||||
|
if true {
|
||||||
|
var v: Bool = false
|
||||||
|
expectIsBooleanType(&v)
|
||||||
|
expectFalse(v.boolValue)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
var v: Bool = true
|
||||||
|
expectTrue(v.boolValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("Printable") {
|
||||||
|
if true {
|
||||||
|
let v: Bool = false
|
||||||
|
expectEqual("false", toString(v))
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
let v: Bool = true
|
||||||
|
expectEqual("true", toString(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("Equatable,Hashable") {
|
||||||
|
checkHashable(true, false, false)
|
||||||
|
checkHashable(false, false, true)
|
||||||
|
checkHashable(true, true, true)
|
||||||
|
|
||||||
|
expectNotEqual(false.hashValue, true.hashValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("!") {
|
||||||
|
if true {
|
||||||
|
let v: Bool = false
|
||||||
|
var r = !v
|
||||||
|
expectType(Bool.self, &r)
|
||||||
|
expectTrue(r)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
let v: Bool = true
|
||||||
|
var r = !v
|
||||||
|
expectType(Bool.self, &r)
|
||||||
|
expectFalse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoolTestSuite.test("!") {
|
||||||
|
let v: Bool = false
|
||||||
|
if true {
|
||||||
|
var r = (v == v)
|
||||||
|
expectType(Bool.self, &r)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
var r = (v != v)
|
||||||
|
expectType(Bool.self, &r)
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
var r = !v
|
||||||
|
expectType(Bool.self, &r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
runAllTests()
|
runAllTests()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user