I noticed (in optimized builds) that dead code stripping didn't seem to be performed for sqrt, while it did when replacing sqrt with eg exp.
What's the reason for this?
Here's a little program to demonstrate it:
import Cocoa // (For CACurrentMediaTime)
struct DeadCodeEliminationTester {
var usedValue: UInt64 = 0 // Will be printed at the end. Non-ignored results are xored into this value.
// Function that returns the time (in seconds) it takes to make a
// hundred million calls to fn, using or ignoring the result of the calls.
mutating func timeLotsOfCallsTo(fn: (Double) -> Double, useResults: Bool) -> Double {
let startTime = CACurrentMediaTime()
var temporaryUsedValue: UInt64 = 0
for i in 0 ..< 100_000_000 {
let doubleResult = fn(Double(i))
temporaryUsedValue ^= unsafeBitCast(doubleResult, UInt64.self)
}
let stopTime = CACurrentMediaTime()
if useResults { usedValue ^= temporaryUsedValue }
return stopTime - startTime
}
mutating func testFunction(fn: (Double) -> Double, label: String) {
let timeUsing = timeLotsOfCallsTo(fn, useResults: true)
let timeIgnoring = timeLotsOfCallsTo(fn, useResults: false)
let ratio = timeUsing / timeIgnoring // Will be close to 1.0 if no dead code elimination was performed, big otherwise.
let clearText = ratio > 100.0 ? "Dead code eliminated!" : " No dead code? "
print(label, clearText,
String(format: "( timeUsing: %.10f | timeIgnoring: %.10f | ratio: % 12.2f )", timeUsing, timeIgnoring, ratio))
}
func useUsedResults() {
print("\n(Printing this: \(String(usedValue, radix: 36)) just to make extra sure the used results are actually considered used.)")
}
}
var t = DeadCodeEliminationTester()
t.testFunction(exp, label: "exp ")
t.testFunction(abs, label: "abs ")
t.testFunction(cos, label: "cos ")
t.testFunction(log, label: "log ")
t.testFunction(round, label: "round")
t.testFunction(sqrt, label: "sqrt ")
t.testFunction(tan, label: "tan ")
t.testFunction(acos, label: "acos ")
t.useUsedResults()Compiling and running that with Xcode 7.1 beta 2:
$ swiftc -Ounchecked test.swift
$ ./test
exp Dead code eliminated! ( timeUsing: 0.3607922090 | timeIgnoring: 0.0000000300 | ratio: 12023982.45 )
abs Dead code eliminated! ( timeUsing: 0.0676673420 | timeIgnoring: 0.0000000850 | ratio: 796107.57 )
cos Dead code eliminated! ( timeUsing: 2.4501839200 | timeIgnoring: 0.0000000330 | ratio: 74239575.35 )
log Dead code eliminated! ( timeUsing: 0.6963752020 | timeIgnoring: 0.0000000360 | ratio: 19342982.82 )
round Dead code eliminated! ( timeUsing: 0.3099052790 | timeIgnoring: 0.0000000330 | ratio: 9390003.80 )
sqrt No dead code? ( timeUsing: 0.4656082430 | timeIgnoring: 0.4724121530 | ratio: 0.99 )
tan No dead code? ( timeUsing: 2.9236285690 | timeIgnoring: 2.9138148010 | ratio: 1.00 )
acos No dead code? ( timeUsing: 0.4560453720 | timeIgnoring: 0.4093574440 | ratio: 1.11 )
(Printing this: 1eazf78rd4j7q just to make extra sure the used results are actually considered used.)AFAICS, the only thing that separates those two groups of example functions is that when you cmd-click on them, you are taken to either
Darwin
or
Darwin -> C -> math
Don't know what to make of it though. Filed 22828651 anyway.