aboutsummaryrefslogtreecommitdiffstats
path: root/test/CodeGen/ARM/thumb1-varalloc.ll
blob: 8d5888d38f9718b18e00354fa13a4956d7a3cfea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
; RUN: llc < %s -mtriple=thumbv6-apple-darwin | FileCheck %s
; RUN: llc < %s -mtriple=thumbv6-apple-darwin -regalloc=basic | FileCheck %s
; RUN: llc < %s -o %t -filetype=obj -mtriple=thumbv6-apple-darwin
; RUN: llvm-objdump -triple=thumbv6-apple-darwin -d %t | FileCheck %s

@__bar = external hidden global i8*
@__baz = external hidden global i8*

; rdar://8819685
define i8* @_foo() {
entry:
; CHECK-LABEL: foo:

	%size = alloca i32, align 4
	%0 = load i8** @__bar, align 4
	%1 = icmp eq i8* %0, null
	br i1 %1, label %bb1, label %bb3
; CHECK: bne
		
bb1:
	store i32 1026, i32* %size, align 4
	%2 = alloca [1026 x i8], align 1
; CHECK: mov     [[R0:r[0-9]+]], sp
; CHECK: adds    {{r[0-9]+}}, [[R0]], {{r[0-9]+}}
	%3 = getelementptr inbounds [1026 x i8]* %2, i32 0, i32 0
	%4 = call i32 @_called_func(i8* %3, i32* %size) nounwind
	%5 = icmp eq i32 %4, 0
	br i1 %5, label %bb2, label %bb3
	
bb2:
	%6 = call i8* @strdup(i8* %3) nounwind
	store i8* %6, i8** @__baz, align 4
	br label %bb3
	
bb3:
	%.0 = phi i8* [ %0, %entry ], [ %6, %bb2 ], [ %3, %bb1 ]
; CHECK: subs    r4, #5
; CHECK-NEXT: mov     sp, r4
; CHECK-NEXT: pop     {r4, r5, r6, r7, pc}
	ret i8* %.0
}

declare noalias i8* @strdup(i8* nocapture) nounwind
declare i32 @_called_func(i8*, i32*) nounwind

; Variable ending up at unaligned offset from sp (i.e. not a multiple of 4)
define void @test_local_var_addr() {
; CHECK-LABEL: test_local_var_addr:

  %addr1 = alloca i8
  %addr2 = alloca i8

; CHECK: mov r0, sp
; CHECK: adds r0, #{{[0-9]+}}
; CHECK: blx
  call void @take_ptr(i8* %addr1)

; CHECK: mov r0, sp
; CHECK: adds r0, #{{[0-9]+}}
; CHECK: blx
  call void @take_ptr(i8* %addr2)

  ret void
}

; Simple variable ending up *at* sp.
define void @test_simple_var() {
; CHECK-LABEL: test_simple_var:

  %addr32 = alloca i32
  %addr8 = bitcast i32* %addr32 to i8*

; CHECK: mov r0, sp
; CHECK-NOT: adds r0
; CHECK: blx
  call void @take_ptr(i8* %addr8)
  ret void
}

; Simple variable ending up at aligned offset from sp.
define void @test_local_var_addr_aligned() {
; CHECK-LABEL: test_local_var_addr_aligned:

  %addr1.32 = alloca i32
  %addr1 = bitcast i32* %addr1.32 to i8*
  %addr2.32 = alloca i32
  %addr2 = bitcast i32* %addr2.32 to i8*

; CHECK: add r0, sp, #{{[0-9]+}}
; CHECK: blx
  call void @take_ptr(i8* %addr1)

; CHECK: mov r0, sp
; CHECK-NOT: add r0
; CHECK: blx
  call void @take_ptr(i8* %addr2)

  ret void
}

; Simple variable ending up at aligned offset from sp.
define void @test_local_var_big_offset() {
; CHECK-LABEL: test_local_var_big_offset:
  %addr1.32 = alloca i32, i32 257
  %addr1 = bitcast i32* %addr1.32 to i8*
  %addr2.32 = alloca i32, i32 257

; CHECK: add [[RTMP:r[0-9]+]], sp, #1020
; CHECK: adds [[RTMP]], #8
; CHECK: blx
  call void @take_ptr(i8* %addr1)

  ret void
}

; Max range addressable with tADDrSPi
define void @test_local_var_offset_1020() {
; CHECK-LABEL: test_local_var_offset_1020
  %addr1 = alloca i8, i32 4
  %addr2 = alloca i8, i32 1020

; CHECK: add r0, sp, #1020
; CHECK-NEXT: blx
  call void @take_ptr(i8* %addr1)

  ret void
}

; Max range addressable with tADDrSPi + tADDi8
define void @test_local_var_offset_1275() {
; CHECK-LABEL: test_local_var_offset_1275
  %addr1 = alloca i8, i32 1
  %addr2 = alloca i8, i32 1275

; CHECK: add r0, sp, #1020
; CHECK: adds r0, #255
; CHECK-NEXT: blx
  call void @take_ptr(i8* %addr1)

  ret void
}

declare void @take_ptr(i8*)