transform: fix incorrect alignment of heap-to-stack transform

It assumed the maximum alignment was equal to sizeof(void*), which is
definitely not the case. So this only worked more or less by accident
previously.

It now uses the alignment as specified by the frontend, or else
`unsafe.Alignof(complex128)` which is typically the maximum alignment of
a given platform (though this shouldn't really happen in practice: the
optimizer should keep the 'align' attribute in place).
This commit is contained in:
Ayke van Laethem
2024-06-25 20:14:05 +02:00
committed by Ron Evans
parent 571447c7c1
commit e6caa3fe9e
5 changed files with 62 additions and 31 deletions
+14 -17
View File
@@ -29,10 +29,14 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
targetData := llvm.NewTargetData(mod.DataLayout())
defer targetData.Dispose()
ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
builder := mod.Context().NewBuilder()
ctx := mod.Context()
builder := ctx.NewBuilder()
defer builder.Dispose()
// Determine the maximum alignment on this platform.
complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)
maxAlign := int64(targetData.ABITypeAlignment(complex128Type))
for _, heapalloc := range getUses(allocator) {
logAllocs := printAllocs != nil && printAllocs.MatchString(heapalloc.InstructionParent().Parent().Name())
if heapalloc.Operand(0).IsAConstantInt().IsNil() {
@@ -90,21 +94,14 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
}
// The pointer value does not escape.
// Determine the appropriate alignment of the alloca. The size of the
// allocation gives us a hint what the alignment should be.
var alignment int
if size%2 != 0 {
alignment = 1
} else if size%4 != 0 {
alignment = 2
} else if size%8 != 0 {
alignment = 4
} else {
alignment = 8
}
if pointerAlignment := targetData.ABITypeAlignment(ptrType); pointerAlignment < alignment {
// Use min(alignment, alignof(void*)) as the alignment.
alignment = pointerAlignment
// Determine the appropriate alignment of the alloca.
attr := heapalloc.GetCallSiteEnumAttribute(0, llvm.AttributeKindID("align"))
alignment := int(maxAlign)
if !attr.IsNil() {
// 'align' return value attribute is set, so use it.
// This is basically always the case, but to be sure we'll default
// to maxAlign if it isn't.
alignment = int(attr.GetEnumValue())
}
// Insert alloca in the entry block. Do it here so that mem2reg can