I feel it's worth taking a look (from a reasonably high-level) at what the compiler does here. If we take a look at the canonical SIL emitted for:
struct Point {
    var x = 0.0
    mutating func add(_ t: Double){
        x += t
    }
}
var p = Point()
p.add(1)
We can see that the add(_:) method gets emitted as:
// Point.add(Double) -> ()
sil hidden @main.Point.add (Swift.Double) -> () :
           $@convention(method) (Double, @inout Point) -> () {
// %0                                             // users: %7, %2
// %1                                             // users: %4, %3
bb0(%0 : $Double, %1 : $*Point):
  // get address of the property 'x' within the point instance.
  %4 = struct_element_addr %1 : $*Point, #Point.x, loc "main.swift":14:9, scope 5 // user: %5
  // get address of the internal property '_value' within the Double instance.
  %5 = struct_element_addr %4 : $*Double, #Double._value, loc "main.swift":14:11, scope 5 // users: %9, %6
  // load the _value from the property address.
  %6 = load %5 : $*Builtin.FPIEEE64, loc "main.swift":14:11, scope 5 // user: %8
  // get the _value from the double passed into the method.
  %7 = struct_extract %0 : $Double, #Double._value, loc "main.swift":14:11, scope 5 // user: %8
  // apply a builtin floating point addition operation (this will be replaced by an 'fadd' instruction in IR gen).
  %8 = builtin "fadd_FPIEEE64"(%6 : $Builtin.FPIEEE64, %7 : $Builtin.FPIEEE64) : $Builtin.FPIEEE64, loc "main.swift":14:11, scope 5 // user: %9
  // store the result to the address of the _value property of 'x'.
  store %8 to %5 : $*Builtin.FPIEEE64, loc "main.swift":14:11, scope 5 // id: %9
  %10 = tuple (), loc "main.swift":14:11, scope 5
  %11 = tuple (), loc "main.swift":15:5, scope 5  // user: %12
  return %11 : $(), loc "main.swift":15:5, scope 5 // id: %12
} // end sil function 'main.Point.add (Swift.Double) -> ()'
(by running xcrun swiftc -emit-sil main.swift | xcrun swift-demangle > main.silgen)
The important thing here is how Swift treats the implicit self parameter. You can see that it's been emitted as an @inout parameter, meaning that it'll be passed by reference into the function.
In order to perform the mutation of the x property, the struct_element_addr SIL instruction is used in order to lookup its address, and then the underlying _value property of the Double. The resultant double is then simply stored back at that address with the store instruction.
What this means is that the add(_:) method is able to directly change the value of p's x property in memory without creating any intermediate instances of Point.