I would like to do some (micro)benchmarking in Swift. I have been using package-benchmark for this. It comes with a blackHole helper function that forces the compiler to assume that a variable is read and thus prevent dead-code elimination.
However, I would like to go a step further and block common subexpression elimination and loop-invariant code motion too. For that I had come up with the following based on the blackHole implementation.
@_optimize(none)
func assumePointeeIsClobbered(_ x: UnsafeMutableRawPointer) {}
My understanding is that this should force the compiler to assume that x can be both read and written to. I tried to use this in the following manner.
@_optimize(none)
func assumePointeeIsClobbered(_ x: UnsafeMutableRawPointer) {}
import Foundation
// NB: I know that this is a very synthetic benchmark that doesn't even measure the latency of sqrt properly, but that is not the point of this question
func sqrtFPI(iter: Int) {
var x = 3.1415926e104
let startTime = DispatchTime.now()
for _ in 1...iter {
assumePointeeIsClobbered(&x)
var result = sqrt(x)
assumePointeeIsClobbered(&result)
}
let endTime = DispatchTime.now()
print(endTime, startTime)
}
But, the sqrt
call gets optimized out by the compiler in Swift 6.0.3, but not in 5.10. Compiler Explorer Link.
The diff shows that the benchmarkee (sqrt) gets optimized out in Swift 6.0.3, but not in Swift 5.10. I have the following questions.
- Is the behavior in Swift 6.0.3 a bug? If not, then what exactly is the optimizer's view of the function? I.e. why exactly is it allowed to do this transformation?
- Is there a better way to implement
assumePointeeIsClobbered
?
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744917997a4600955.html
评论列表(0条)