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.
Этот коммит содержится в:
родитель
dcffbc49c4
коммит
e5029c63d1
1 изменённых файлов: 21 добавлений и 0 удалений
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче