Skip to content

test that various pointer types hit UTF8 decoding fast path #21743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions test/SILOptimizer/utf8_decoding_fastpath.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// RUN: %target-swift-frontend -Xllvm -swiftmergefunc-threshold=0 -parse-as-library -O -target-cpu core2 -emit-ir %s | %FileCheck %s
// REQUIRES: optimized_stdlib,CPU=x86_64

// This is an end-to-end test to ensure that the optimizer generates
// good code for various ways to create a String from a Sequence of UTF-8
// bytes for which a fast path exists.

// Please note: this test targets "core2" to ensure consistent output
// on all x86 host processors.

@inline(never)
func blackhole<T>(_ value: T) {}

// UnsafeBufferPointer<UInt8>
// ==========================
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}s22utf8_decoding_fastpath15decodeUBPAsUTF8ySSSRys5UInt8VGF{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: ret
public func decodeUBPAsUTF8(_ ptr: UnsafeBufferPointer<UInt8>) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// UnsafeMutableBufferPointer<UInt8>
// =================================
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}s22utf8_decoding_fastpath16decodeUMBPAsUTF8ySSSrys5UInt8VGF{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: ret
public func decodeUMBPAsUTF8(_ ptr: UnsafeMutableBufferPointer<UInt8>) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// Array<UInt8>
// ============
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeArrayAsUTF8{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: ret
public func decodeArrayAsUTF8(_ ptr: [UInt8]) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// UnsafeRawBufferPointer
// ======================
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeURBPAsUTF8{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: ret
public func decodeURBPAsUTF8(_ ptr: UnsafeRawBufferPointer) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// UnsafeMutableRawBufferPointer
// =============================
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeUMRBPAsUTF8{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: ret
public func decodeUMRBPAsUTF8(_ ptr: UnsafeMutableRawBufferPointer) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// String.UTF8View
// ===============
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeStringUTF8ViewAs{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: br
public func decodeStringUTF8ViewAsUTF8(_ ptr: String.UTF8View) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// Substring.UTF8View
// ==================
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeSubstringUTF8ViewAs{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: br
public func decodeSubstringUTF8ViewAsUTF8(_ ptr: Substring.UTF8View) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}

// Slice<UBP>
// ==========
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeUBPSliceAsUTF8{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK-LAST: br
public func decodeUBPSliceAsUTF8(_ ptr: Slice<UnsafeBufferPointer<UInt8>>) -> String {
return String(decoding: ptr, as: Unicode.UTF8.self)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you file a bug and directly link it in the comment? Unless the test is XFAIL, I think it's better to disable the check than to test the undesired behavior. You can say something like:

// CHECK-LABEL: define swiftcc {{.*}}decodeUBPSliceAsUTF8{{.*}}
//
// ... comment linking and explaining bug, to be reenabled when fixed
// xCHECK-NOT: {{.*}} = call swiftcc {{.*}}_fromCodeUnits{{.*}}
// xCHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
//
// CHECK: ret

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say checking the undesired behavior is better because the test'll tell you if it changes for the better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@milseman up to you which way, I did file a bug

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with @jrose-apple's suggestion, but make it a little more explicit that you're checking against current behavior rather than desired behavior. Something like:

// FIXME(https://bugs.swift.org/browse/SR-9700):  _fromUTF8Repairing instead of _fromCodeUnits.
// Currently, Slice<UBP> doesn't actually work. Swap checked function below when resolved.

And then probably link to this specific test in the bug itself, so the resolver knows where to expect a change.


// Slice<URBP>
// ===========
// CHECK-LABEL: define {{.*}}swiftcc {{.*}}decodeURBPSliceAsUTF8{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: {{.*}} = call swiftcc {{.*}} @"$sSS18_fromUTF8Repairing{{.*}}
// CHECK-NOT: _fromCodeUnits
// CHECK: ret
public func decodeURBPSliceAsUTF8(_ ptr: Slice<UnsafeBufferPointer<UInt8>>) -> String {
blackhole("foo") // otherwise it just jumps into the Slice<UBP> version
return String(decoding: ptr, as: Unicode.UTF8.self)
}