llvm / llvm/llvm-project

[SROA] Aggregate-to-vector rewriting introduces stack realignment despite DataLayout S64

Open
#222,966 0 comments 0 reactions 0 assignees View on GitHub
llvm:optimizations
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

SROA can increase an alloca's alignment beyond the natural stack alignment specified by the data layout. On SystemZ, a five-pointer structure allocated with alignment 8 becomes `<5 x ptr>` with alignment 64, introducing dynamic alignment of the stack allocation.

Reproduced on LLVM 24.0.0git (`1952c705fad0`), targeting `s390x-unknown-linux-gnu`.

## Reproducer

Save as `repro.ll`:

```llvm
target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64-S64"
target triple = "s390x-unknown-linux-gnu"

%ptr5 = type { ptr, ptr, ptr, ptr, ptr }

declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1 immarg)

define void @spill_ptr5(ptr %src) {
entry:
%slot = alloca %ptr5, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %slot, ptr align 8 %src,
i64 40, i1 true)
ret void
}
```

```sh
opt -passes='sroa' -S repro.ll -o sroa.ll
llc repro.ll -o before.s
llc sroa.ll -o after.s
```

SROA changes:

```llvm
%slot = alloca %ptr5, align 8
```

to:

```llvm
%slot.sroa.0 = alloca <5 x ptr>, align 64
%slot.sroa.0.0.copyload = load volatile <5 x ptr>, ptr %src, align 8
store volatile <5 x ptr> %slot.sroa.0.0.copyload, ptr %slot.sroa.0, align 64
```

The original input generates a fixed stack frame. After SROA, SystemZ code generation includes:

```asm
lgr %r1, %r15
aghi %r1, -120
la %r3, 216(%r1)
nill %r3, 65472
lgr %r15, %r1
```

The `nill` clears the low six bits of the allocation address, dynamically aligning it to 64 bytes.

## Cause and expected behavior

SystemZ's [native data layout](https://github.com/llvm/llvm-project/blob/1952c705fad0187fc0c6fbd1460dbd56d56c8087/llvm/lib/TargetParser/TargetDataLayout.cpp#L366-L408) specifies `S64`. The [LangRef](https://github.com/llvm/llvm-project/blob/1952c705fad0187fc0c6fbd1460dbd56d56c8087/llvm/docs/LangRef.md#L3523-L3528) describes this as a limit on stack-variable alignment promotion to avoid dynamic stack realignment.

In [SROA::rewritePartition](https://github.com/llvm/llvm-project/blob/1952c705fad0187fc0c6fbd1460dbd56d56c8087/llvm/lib/Transforms/Scalar/SROA.cpp#L5579-L5588), the replacement alloca takes `DL.getPrefTypeAlign(PartitionTy)` when the existing alignment is no greater than the replacement type's ABI alignment. For `<5 x ptr>`, this selects 64 bytes without consulting `DL.getStackAlignment()`.

Cap the preferred alignment at the natural stack alignment, while preserving any stronger alignment required by the original allocation. This keeps the replacement at alignment 8 in this example and avoids the dynamic alignment sequence.

Assisted-by: OpenAI Codex

Contributor guide

Open the contributing guide

Research direction

Start in llvm/lib/Transforms/Scalar/SROA.cpp at SROA::rewritePartition and compare the replacement alignment with DataLayout's stack alignment. Run the supplied opt and llc commands for the SystemZ reproducer. Done means the replacement remains aligned to 8 in this case while preserving stronger original alignment and avoiding the dynamic stack realignment sequence.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.