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.
Этот коммит содержится в:
Ayke van Laethem 2019-04-07 16:37:57 +02:00 коммит произвёл Ron Evans
родитель dcffbc49c4
коммит 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
}