mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 03:53:42 +00:00
compiler: optimize ptrtoint+add+inttoptr pattern
This pattern is often used in some runtime intrinsics (especially the ones related to slices) to do pointer arithmetic with unsafe.Pointer and uintptr because Go does not support pointer arithmetic. Recognizing this pattern and replacing it with a gep instruction improves code size in various tests.
This commit is contained in:
committed by
Ron Evans
parent
dcffbc49c4
commit
e5029c63d1
@@ -2504,6 +2504,27 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
||||
if isPtrFrom && !isPtrTo {
|
||||
return c.builder.CreatePtrToInt(value, llvmTypeTo, ""), nil
|
||||
} else if !isPtrFrom && isPtrTo {
|
||||
if !value.IsABinaryOperator().IsNil() && value.InstructionOpcode() == llvm.Add {
|
||||
// This is probably a pattern like the following:
|
||||
// unsafe.Pointer(uintptr(ptr) + index)
|
||||
// Used in functions like memmove etc. for lack of pointer
|
||||
// arithmetic. Convert it to real pointer arithmatic here.
|
||||
ptr := value.Operand(0)
|
||||
index := value.Operand(1)
|
||||
if !index.IsAPtrToIntInst().IsNil() {
|
||||
// Swap if necessary, if ptr and index are reversed.
|
||||
ptr, index = index, ptr
|
||||
}
|
||||
if !ptr.IsAPtrToIntInst().IsNil() {
|
||||
origptr := ptr.Operand(0)
|
||||
if origptr.Type() == c.i8ptrType {
|
||||
// This pointer can be calculated from the original
|
||||
// ptrtoint instruction with a GEP. The leftover inttoptr
|
||||
// instruction is trivial to optimize away.
|
||||
return c.builder.CreateGEP(origptr, []llvm.Value{index}, ""), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.builder.CreateIntToPtr(value, llvmTypeTo, ""), nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user