Skip to content

Commit

Permalink
GlobalISel (AArch64): fix ABI at border between GPRs and SP.
Browse files Browse the repository at this point in the history
If a struct would end up half in GPRs and half on SP the ABI says it should
actually go entirely on the stack. We were getting this wrong in GlobalISel
before, causing compatibility issues.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311137 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
TNorthover committed Aug 17, 2017
1 parent d93db26 commit e8fd209
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/Target/AArch64/AArch64CallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,16 @@ void AArch64CallLowering::splitToValueTypes(
}

unsigned FirstRegIdx = SplitArgs.size();
bool AlreadySplit = false;
for (auto SplitVT : SplitVTs) {
// FIXME: set split flags if they're actually used (e.g. i128 on AAPCS).
Type *SplitTy = SplitVT.getTypeForEVT(Ctx);
SplitArgs.push_back(
ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*SplitTy, DL)),
SplitTy, OrigArg.Flags, OrigArg.IsFixed});
if (!AlreadySplit) {
SplitArgs.back().Flags.setSplit();
AlreadySplit = true;
}
}

for (unsigned i = 0; i < Offsets.size(); ++i)
Expand Down
39 changes: 39 additions & 0 deletions test/CodeGen/AArch64/GlobalISel/call-translator.ll
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,42 @@ define void @test_call_stack() {
define void @test_mem_i1([8 x i64], i1 %in) {
ret void
}

; CHECK-LABEL: name: test_split_struct
; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD {{.*}}(p0)
; CHECK: [[LO:%[0-9]+]](s64) = G_EXTRACT [[STRUCT]](s128), 0
; CHECK: [[HI:%[0-9]+]](s64) = G_EXTRACT [[STRUCT]](s128), 64

; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
; CHECK: [[OFF:%[0-9]+]](s64) = G_CONSTANT i64 0
; CHECK: [[ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[OFF]]
; CHECK: G_STORE [[LO]](s64), [[ADDR]](p0) :: (store 8 into stack, align 0)

; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
; CHECK: [[OFF:%[0-9]+]](s64) = G_CONSTANT i64 8
; CHECK: [[ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[OFF]]
; CHECK: G_STORE [[HI]](s64), [[ADDR]](p0) :: (store 8 into stack + 8, align 0)
define void @test_split_struct([2 x i64]* %ptr) {
%struct = load [2 x i64], [2 x i64]* %ptr
call void @take_split_struct([2 x i64]* null, i64 1, i64 2, i64 3,
i64 4, i64 5, i64 6,
[2 x i64] %struct)
ret void
}

; CHECK-LABEL: name: take_split_struct
; CHECK: fixedStack:
; CHECK-DAG: - { id: [[LO_FRAME:[0-9]+]], type: default, offset: 0, size: 8
; CHECK-DAG: - { id: [[HI_FRAME:[0-9]+]], type: default, offset: 8, size: 8

; CHECK: [[LOPTR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[LO_FRAME]]
; CHECK: [[LO:%[0-9]+]](s64) = G_LOAD [[LOPTR]](p0) :: (invariant load 8 from %fixed-stack.[[LO_FRAME]], align 0)

; CHECK: [[HIPTR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[HI_FRAME]]
; CHECK: [[HI:%[0-9]+]](s64) = G_LOAD [[HIPTR]](p0) :: (invariant load 8 from %fixed-stack.[[HI_FRAME]], align 0)
define void @take_split_struct([2 x i64]* %ptr, i64, i64, i64,
i64, i64, i64,
[2 x i64] %in) {
store [2 x i64] %in, [2 x i64]* %ptr
ret void
}

0 comments on commit e8fd209

Please sign in to comment.