mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
2d43b2fbd5
An instruction like this will need to allocate some stack space for the last parameter: %x = call addrspace(1) i16 @bar(i64 undef, i64 undef, i16 undef, i16 0) This worked fine when passing an actual value (in this case 0). However, when passing undef, no value was pushed to the stack and therefore no push instructions were created. This caused an unbalanced stack leading to interesting results. This commit fixes that by replacing the push logic with a regular stack adjustment and stack-relative load/stores. This is less efficient but at least it correctly compiles the code. I can think of a few improvements in the future: * The stack should have been adjusted in the function prologue when there are no allocas in the function. * Many (if not most) stack adjustments can be replaced by pushing/popping the values directly. Exactly like the previous code attempted but didn't do correctly. * Small stack adjustments can be done more efficiently with a few push/pop instructions (pushing/popping bogus values), both for code size and for speed. All in all, as long as there are no allocas in the function I think that it is almost always more efficient to emit regular push/pop instructions. This is however left for future optimizations. Differential Revision: https://reviews.llvm.org/D78581
97 lines
2.5 KiB
LLVM
97 lines
2.5 KiB
LLVM
; RUN: llc < %s -march=avr | FileCheck %s
|
|
|
|
declare void @foo(i16*, i16*, i8*)
|
|
|
|
define void @test1(i16 %x) {
|
|
; CHECK-LABEL: test1:
|
|
; CHECK: out 61, r28
|
|
; SP copy
|
|
; CHECK-NEXT: in [[SPCOPY1:r[0-9]+]], 61
|
|
; CHECK-NEXT: in [[SPCOPY2:r[0-9]+]], 62
|
|
; allocate first dynalloca
|
|
; CHECK: in {{.*}}, 61
|
|
; CHECK: in {{.*}}, 62
|
|
; CHECK: sub
|
|
; CHECK: sbc
|
|
; CHECK: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, {{.*}}
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, {{.*}}
|
|
; Test writes
|
|
; CHECK: std Z+12, {{.*}}
|
|
; CHECK: std Z+13, {{.*}}
|
|
; CHECK: std Z+7, {{.*}}
|
|
; CHECK-NOT: std
|
|
; Test SP restore
|
|
; CHECK: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, [[SPCOPY2]]
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, [[SPCOPY1]]
|
|
%a = alloca [8 x i16]
|
|
%vla = alloca i16, i16 %x
|
|
%add = shl nsw i16 %x, 1
|
|
%vla1 = alloca i8, i16 %add
|
|
%arrayidx = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16 0, i16 2
|
|
store i16 3, i16* %arrayidx
|
|
%arrayidx2 = getelementptr inbounds i16, i16* %vla, i16 6
|
|
store i16 4, i16* %arrayidx2
|
|
%arrayidx3 = getelementptr inbounds i8, i8* %vla1, i16 7
|
|
store i8 44, i8* %arrayidx3
|
|
%arraydecay = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16 0, i16 0
|
|
call void @foo(i16* %arraydecay, i16* %vla, i8* %vla1)
|
|
ret void
|
|
}
|
|
|
|
declare void @foo2(i16*, i64, i64, i64)
|
|
|
|
; Test that arguments are passed through pushes into the call instead of
|
|
; allocating the call frame space in the prologue. Also test that SP is restored
|
|
; after the call frame is restored and not before.
|
|
define void @dynalloca2(i16 %x) {
|
|
; CHECK-LABEL: dynalloca2:
|
|
; CHECK: in [[SPCOPY1:r[0-9]+]], 61
|
|
; CHECK: in [[SPCOPY2:r[0-9]+]], 62
|
|
; Allocate stack space for call
|
|
; CHECK: in {{.*}}, 61
|
|
; CHECK: in {{.*}}, 62
|
|
; CHECK: subi
|
|
; CHECK: sbci
|
|
; CHECK: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, {{.*}}
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, {{.*}}
|
|
; Store values on the stack
|
|
; CHECK: ldi r16, 0
|
|
; CHECK: ldi r17, 0
|
|
; CHECK: std Z+5, r16
|
|
; CHECK: std Z+6, r17
|
|
; CHECK: std Z+7, r16
|
|
; CHECK: std Z+8, r17
|
|
; CHECK: std Z+3, r16
|
|
; CHECK: std Z+4, r17
|
|
; CHECK: std Z+1, r16
|
|
; CHECK: std Z+2, r17
|
|
; CHECK: call
|
|
; Call frame restore
|
|
; CHECK-NEXT: in r30, 61
|
|
; CHECK-NEXT: in r31, 62
|
|
; CHECK-NEXT: adiw r30, 8
|
|
; CHECK-NEXT: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, r31
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, r30
|
|
; SP restore
|
|
; CHECK: in r0, 63
|
|
; CHECK-NEXT: cli
|
|
; CHECK-NEXT: out 62, r7
|
|
; CHECK-NEXT: out 63, r0
|
|
; CHECK-NEXT: out 61, r6
|
|
%vla = alloca i16, i16 %x
|
|
call void @foo2(i16* %vla, i64 0, i64 0, i64 0)
|
|
ret void
|
|
}
|