
The x/tools/go/ssa package splits slice loads/stores into two operations. So for code like this: x = p[3] It has two instructions: x_ptr = &p[3] x = *x_ptr This makes the IR simpler, but also means we're accidentally inserting more nil checks than necessary: the slice index operation has effectively already checked for nil by performing a bounds check. Therefore, omit nil pointer checks for pointers created by *ssa.IndexAddr. This change is necessary to make sure a future removal of runtime.isnil will not cause the escape analysis pass to regress. Apart from that, it reduces code size slightly in many smoke tests (with no increases in code size).
30 строки
936 Б
Go
30 строки
936 Б
Go
package compiler
|
|
|
|
// This file implements volatile loads/stores in runtime/volatile.LoadT and
|
|
// runtime/volatile.StoreT as compiler builtins.
|
|
|
|
import (
|
|
"golang.org/x/tools/go/ssa"
|
|
"tinygo.org/x/go-llvm"
|
|
)
|
|
|
|
// createVolatileLoad is the implementation of the intrinsic function
|
|
// runtime/volatile.LoadT().
|
|
func (b *builder) createVolatileLoad(instr *ssa.CallCommon) (llvm.Value, error) {
|
|
addr := b.getValue(instr.Args[0])
|
|
b.createNilCheck(instr.Args[0], addr, "deref")
|
|
val := b.CreateLoad(addr, "")
|
|
val.SetVolatile(true)
|
|
return val, nil
|
|
}
|
|
|
|
// createVolatileStore is the implementation of the intrinsic function
|
|
// runtime/volatile.StoreT().
|
|
func (b *builder) createVolatileStore(instr *ssa.CallCommon) (llvm.Value, error) {
|
|
addr := b.getValue(instr.Args[0])
|
|
val := b.getValue(instr.Args[1])
|
|
b.createNilCheck(instr.Args[0], addr, "deref")
|
|
store := b.CreateStore(val, addr)
|
|
store.SetVolatile(true)
|
|
return llvm.Value{}, nil
|
|
}
|