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
[SR-13985] TempRValueOpt causes a failure when building swift-numerics #56380
Comments
@swift-ci create |
Reduced this some: // %swift_frontend_plain -c %s -target x86_64-unknown-linux-gnu -O -parse-as-library -o /dev/null -sil-verify-all
public struct Complex<RealType> where RealType: FloatingPoint {
@usableFromInline
internal var x: RealType
@usableFromInline
internal var y: RealType
@_transparent
public init(_ real: RealType, _ imaginary: RealType) {
x = real
y = imaginary
}
}
extension Complex {
public var phase: RealType { fatalError() }
}
extension Complex {
public static func log(_ z: Complex, _ b: Bool) -> Complex {
let θ = z.phase
if b == true {
return Complex(.infinity, θ)
}
return Complex(.infinity, θ)
}
} |
Slightly lower form: // RUN: %sil-opt --temp-rvalue-opt %s -o /dev/null
sil_stage canonical
import Builtin
import Swift
import SwiftShims
public struct Complex<RealType> where RealType : FloatingPoint {
@usableFromInline
@_hasStorage internal var x: RealType { get set }
@usableFromInline
@_hasStorage internal var y: RealType { get set }
init(_ real: RealType, _ imaginary: RealType)
}
extension Complex {
var phase: RealType { get }
}
extension Complex {
public static func log(_ z: Complex<RealType>, _ b: Bool) -> Complex<RealType>
}
// Complex.phase.getter
sil hidden [ossa] @$s7reduced7ComplexV5phasexvg : $@convention(method) <RealType where RealType : FloatingPoint> (@in_guaranteed Complex<RealType>) -> @out RealType {
// %0 "$return_value"
// %1 "self" // user: %2
bb0(%0 : $*RealType, %1 : $*Complex<RealType>):
debug_value_addr %1 : $*Complex<RealType>, let, name "self", argno 1 // id: %2
unreachable // id: %3
} // end sil function '$s7reduced7ComplexV5phasexvg'
// static Complex.log(_:_:)
sil [ossa] @$s7reduced7ComplexV3logyACyxGAE_SbtFZ : $@convention(method) <RealType where RealType : FloatingPoint> (@in_guaranteed Complex<RealType>, Bool, @thin Complex<RealType>.Type) -> @out Complex<RealType> {
// %0 "$return_value" // users: %35, %60
// %1 "z" // users: %9, %4
// %2 "b" // users: %15, %5
// %3 "self" // user: %6
bb0(%0 : $*Complex<RealType>, %1 : $*Complex<RealType>, %2 : $Bool, %3 : $@thin Complex<RealType>.Type):
debug_value_addr %1 : $*Complex<RealType>, let, name "z", argno 1 // id: %4
debug_value %2 : $Bool, let, name "b", argno 2 // id: %5
debug_value %3 : $@thin Complex<RealType>.Type, let, name "self", argno 3 // id: %6
%7 = alloc_stack $RealType, let, name "θ" // users: %66, %48, %41, %23, %11
%8 = alloc_stack $Complex<RealType> // users: %13, %12, %11, %9
copy_addr %1 to [initialization] %8 : $*Complex<RealType> // id: %9
// function_ref Complex.phase.getter
%10 = function_ref @$s7reduced7ComplexV5phasexvg : $@convention(method) <τ_0_0 where τ_0_0 : FloatingPoint> (@in_guaranteed Complex<τ_0_0>) -> @out τ_0_0 // user: %11
%11 = apply %10<RealType>(%7, %8) : $@convention(method) <τ_0_0 where τ_0_0 : FloatingPoint> (@in_guaranteed Complex<τ_0_0>) -> @out τ_0_0
destroy_addr %8 : $*Complex<RealType> // id: %12
dealloc_stack %8 : $*Complex<RealType> // id: %13
%14 = integer_literal $Builtin.Int1, -1 // user: %16
%15 = struct_extract %2 : $Bool, #Bool._value // user: %16
%16 = builtin "cmp_eq_Int1"(%15 : $Builtin.Int1, %14 : $Builtin.Int1) : $Builtin.Int1 // user: %17
cond_br %16, bb1, bb2 // id: %17
bb1: // Preds: bb0
%18 = metatype $@thick RealType.Type // user: %21
%19 = alloc_stack $RealType // users: %26, %40, %21
%20 = witness_method $RealType, #FloatingPoint.infinity!getter : <Self where Self : FloatingPoint> (Self.Type) -> () -> Self : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0 // user: %21
%21 = apply %20<RealType>(%19, %18) : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
%22 = alloc_stack $RealType // users: %31, %39, %23
copy_addr [take] %7 to [initialization] %22 : $*RealType // id: %23
%24 = alloc_stack $Complex<RealType> // users: %27, %32, %37, %36, %35
%25 = alloc_stack $RealType // users: %29, %28, %26
copy_addr [take] %19 to [initialization] %25 : $*RealType // id: %26
%27 = struct_element_addr %24 : $*Complex<RealType>, #Complex.x // user: %28
copy_addr [take] %25 to [initialization] %27 : $*RealType // id: %28
dealloc_stack %25 : $*RealType // id: %29
%30 = alloc_stack $RealType // users: %34, %33, %31
copy_addr [take] %22 to [initialization] %30 : $*RealType // id: %31
%32 = struct_element_addr %24 : $*Complex<RealType>, #Complex.y // user: %33
copy_addr [take] %30 to [initialization] %32 : $*RealType // id: %33
dealloc_stack %30 : $*RealType // id: %34
copy_addr %24 to [initialization] %0 : $*Complex<RealType> // id: %35
destroy_addr %24 : $*Complex<RealType> // id: %36
dealloc_stack %24 : $*Complex<RealType> // id: %37
%38 = tuple ()
dealloc_stack %22 : $*RealType // id: %39
dealloc_stack %19 : $*RealType // id: %40
dealloc_stack %7 : $*RealType // id: %41
br bb3 // id: %42
bb2: // Preds: bb0
%43 = metatype $@thick RealType.Type // user: %46
%44 = alloc_stack $RealType // users: %51, %65, %46
%45 = witness_method $RealType, #FloatingPoint.infinity!getter : <Self where Self : FloatingPoint> (Self.Type) -> () -> Self : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0 // user: %46
%46 = apply %45<RealType>(%44, %43) : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
%47 = alloc_stack $RealType // users: %56, %64, %48
copy_addr [take] %7 to [initialization] %47 : $*RealType // id: %48
%49 = alloc_stack $Complex<RealType> // users: %52, %57, %62, %61, %60
%50 = alloc_stack $RealType // users: %54, %53, %51
copy_addr [take] %44 to [initialization] %50 : $*RealType // id: %51
%52 = struct_element_addr %49 : $*Complex<RealType>, #Complex.x // user: %53
copy_addr [take] %50 to [initialization] %52 : $*RealType // id: %53
dealloc_stack %50 : $*RealType // id: %54
%55 = alloc_stack $RealType // users: %59, %58, %56
copy_addr [take] %47 to [initialization] %55 : $*RealType // id: %56
%57 = struct_element_addr %49 : $*Complex<RealType>, #Complex.y // user: %58
copy_addr [take] %55 to [initialization] %57 : $*RealType // id: %58
dealloc_stack %55 : $*RealType // id: %59
copy_addr %49 to [initialization] %0 : $*Complex<RealType> // id: %60
destroy_addr %49 : $*Complex<RealType> // id: %61
dealloc_stack %49 : $*Complex<RealType> // id: %62
%63 = tuple ()
dealloc_stack %47 : $*RealType // id: %64
dealloc_stack %44 : $*RealType // id: %65
dealloc_stack %7 : $*RealType // id: %66
br bb3 // id: %67
bb3: // Preds: bb2 bb1
%68 = tuple () // user: %69
return %68 : $() // id: %69
} // end sil function '$s7reduced7ComplexV3logyACyxGAE_SbtFZ'
sil_property #Complex.x<τ_0_0 where τ_0_0 : FloatingPoint> ()
sil_property #Complex.y<τ_0_0 where τ_0_0 : FloatingPoint> () |
From tracing, what appears to be happening is that the successive iteration for simplifying multiple redundant stores is causing an invalid case to form. What roughly occurs is that a series of passes over: ...
copy_addr [take] %5 to [initialization] %37 : $*RealType
...
copy_addr [take] %34 to [initialization] %40 : $*RealType
...
copy_addr [take] %40 to [initialization] %42 : $*RealType
...
copy_addr [take] %37 to [initialization] %45 : $*RealType
...
copyaddr_ [take] %45 to [initialization] %47 : $*RealType
... Replacing Load: copy_addr [take] %37 to [initialization] %45 : $*RealType
Copy: copy_addr [take] %5 to [initialization] %47 : $*RealType Giving ...
copy_addr [take] %5 to [initialization] %5 : $*RealType
...
copy_addr [take] %34 to [initialization] %39 : $*RealType
...
copy_addr [take] %39 to [initialization] %41 : $*RealType
...
copy_addr %5 to [initialization] %44 : $*RealType
destroy_addr %5 : $*RealType
..
copy_addr [take] %44 to [initialization] %47 : $*RealType Replacing Load: copy_addr [take] %39 to [initialization] %41
Copy: copy_addr [take] %34 to [initialization] %39 Giving ...
copy_addr [take] %5 to [initialization] %5 : $*RealType
...
copy_addr [take] %34 to [initialization] %34 : $*RealType
...
copy_addr [take] %34 to [initialization] %40 : $*RealType
destroy_addr %34
...
copy_addr %5 to [initialization] %43 : $*RealType
destroy_addr %5 : $*RealType
...
copy_addr [take] %43 to [initialization] %46 : $*RealType And for the next (bad) transformation, as it ignores the Load: copy_addr [take] %43 to [initialization] %46
Copy: copy_addr %5 to [initialization] %43 : $*RealType Giving: ...
copy_addr [take] %5 to [initialization] %5 : $*RealType
...
copy_addr [take] %34 to [initialization] %34 : $*RealType
...
copy_addr [take] %34 to [initialization] %40 : $*RealType
destroy_addr %34
...
copy_addr %5 to [initialization] %5 : $*RealType
destroy_addr %5 : $*RealType
...
copy_addr [take] %5 to [initialization] %45 : $*RealType Note that I cannot seem to create a synthetic further reduction as when fed the intermediate state. The interaction seems to involve a conversion of a |
Thanks for providing the reduced test case! |
Additional Detail from JIRA
md5: 9a03190e737cb12bc220336941a2ae02
Issue Description:
When building swift-numerics on Linux with WMO, there is a misoptimization with the TempRValueOpt pass:
SIL memory lifetime failure in @$s13ComplexModule0A0V3logyACyxGAEFZ: memory is not initialized, but should
memory location: %98 = alloc_stack $RealType, let, name "θ" // users: %392, %390, %234, %235, %406,. %247, %100
at instruction: copy_addr %98 to [initialization] %391 : %*RealType // id: %392
Happens with from 2020-11-26 at least to 2020-12-21.
The text was updated successfully, but these errors were encountered: