1; RUN: llc -march=xcore < %s | FileCheck %s
2; RUN: llc -march=xcore -O=0 < %s | FileCheck %s -check-prefix=PHINODE
3
4declare i8 addrspace(1)* @llvm.xcore.getst.p1i8.p1i8(i8 addrspace(1)* %r)
5declare void @llvm.xcore.msync.p1i8(i8 addrspace(1)* %r)
6declare void @llvm.xcore.ssync()
7declare void @llvm.xcore.mjoin.p1i8(i8 addrspace(1)* %r)
8declare void @llvm.xcore.initsp.p1i8(i8 addrspace(1)* %r, i8* %value)
9declare void @llvm.xcore.initpc.p1i8(i8 addrspace(1)* %r, i8* %value)
10declare void @llvm.xcore.initlr.p1i8(i8 addrspace(1)* %r, i8* %value)
11declare void @llvm.xcore.initcp.p1i8(i8 addrspace(1)* %r, i8* %value)
12declare void @llvm.xcore.initdp.p1i8(i8 addrspace(1)* %r, i8* %value)
13
14define i8 addrspace(1)* @test_getst(i8 addrspace(1)* %r) {
15; CHECK-LABEL: test_getst:
16; CHECK: getst r0, res[r0]
17  %result = call i8 addrspace(1)* @llvm.xcore.getst.p1i8.p1i8(i8 addrspace(1)* %r)
18  ret i8 addrspace(1)* %result
19}
20
21define void @test_ssync() {
22; CHECK-LABEL: test_ssync:
23; CHECK: ssync
24  call void @llvm.xcore.ssync()
25  ret void
26}
27
28define void @test_mjoin(i8 addrspace(1)* %r) {
29; CHECK-LABEL: test_mjoin:
30; CHECK: mjoin res[r0]
31  call void @llvm.xcore.mjoin.p1i8(i8 addrspace(1)* %r)
32  ret void
33}
34
35define void @test_initsp(i8 addrspace(1)* %t, i8* %src) {
36; CHECK-LABEL: test_initsp:
37; CHECK: init t[r0]:sp, r1
38  call void @llvm.xcore.initsp.p1i8(i8 addrspace(1)* %t, i8* %src)
39  ret void
40}
41
42define void @test_initpc(i8 addrspace(1)* %t, i8* %src) {
43; CHECK-LABEL: test_initpc:
44; CHECK: init t[r0]:pc, r1
45  call void @llvm.xcore.initpc.p1i8(i8 addrspace(1)* %t, i8* %src)
46  ret void
47}
48
49define void @test_initlr(i8 addrspace(1)* %t, i8* %src) {
50; CHECK-LABEL: test_initlr:
51; CHECK: init t[r0]:lr, r1
52  call void @llvm.xcore.initlr.p1i8(i8 addrspace(1)* %t, i8* %src)
53  ret void
54}
55
56define void @test_initcp(i8 addrspace(1)* %t, i8* %src) {
57; CHECK-LABEL: test_initcp:
58; CHECK: init t[r0]:cp, r1
59  call void @llvm.xcore.initcp.p1i8(i8 addrspace(1)* %t, i8* %src)
60  ret void
61}
62
63define void @test_initdp(i8 addrspace(1)* %t, i8* %src) {
64; CHECK-LABEL: test_initdp:
65; CHECK: init t[r0]:dp, r1
66  call void @llvm.xcore.initdp.p1i8(i8 addrspace(1)* %t, i8* %src)
67  ret void
68}
69
70@tl = thread_local global [3 x i32] zeroinitializer
71@tle = external thread_local global [2 x i32]
72
73define i32* @f_tl() {
74; CHECK-LABEL: f_tl:
75; CHECK: get r11, id
76; CHECK: ldaw [[R0:r[0-9]]], dp[tl]
77; CHECK: ldc [[R1:r[0-9]]], 8
78; CHECK: ldc [[R2:r[0-9]]], 12
79; r0 = id*12 + 8 + &tl
80; CHECK: lmul {{r[0-9]}}, r0, r11, [[R2]], [[R0]], [[R1]]
81  ret i32* getelementptr inbounds ([3 x i32], [3 x i32]* @tl, i32 0, i32 2)
82}
83
84define i32* @f_tle() {
85; CHECK-LABEL: f_tle:
86; CHECK: get r11, id
87; CHECK: shl [[R0:r[0-9]]], r11, 3
88; CHECK: ldaw [[R1:r[0-9]]], dp[tle]
89; r0 = &tl + id*8
90; CHECK: add r0, [[R1]], [[R0]]
91  ret i32* getelementptr inbounds ([2 x i32], [2 x i32]* @tle, i32 0, i32 0)
92}
93
94define i32 @f_tlExpr () {
95; CHECK-LABEL: f_tlExpr:
96; CHECK: get r11, id
97; CHECK: shl [[R0:r[0-9]]], r11, 3
98; CHECK: ldaw [[R1:r[0-9]]], dp[tle]
99; CHECK: add [[R2:r[0-9]]], [[R1]], [[R0]]
100; CHECK: add r0, [[R2]], [[R2]]
101  ret i32 add(
102      i32 ptrtoint( i32* getelementptr inbounds ([2 x i32], [2 x i32]* @tle, i32 0, i32 0) to i32),
103      i32 ptrtoint( i32* getelementptr inbounds ([2 x i32], [2 x i32]* @tle, i32 0, i32 0) to i32))
104}
105
106define void @phiNode1() {
107; N.B. lowering of duplicate constexpr in a PHI node requires -O=0
108; PHINODE-LABEL: phiNode1:
109; PHINODE: get r11, id
110; PHINODE-LABEL: .LBB11_1:
111; PHINODE: get r11, id
112; PHINODE: bu .LBB11_1
113entry:
114  br label %ConstantExpPhiNode
115ConstantExpPhiNode:
116  %ptr = phi i32* [ getelementptr inbounds ([3 x i32], [3 x i32]* @tl, i32 0, i32 0), %entry ],
117                  [ getelementptr inbounds ([3 x i32], [3 x i32]* @tl, i32 0, i32 0), %ConstantExpPhiNode ]
118  br label %ConstantExpPhiNode
119exit:
120  ret void
121}
122
123define void @phiNode2( i1 %bool) {
124; N.B. check an extra 'Node_crit_edge' (LBB12_1) is inserted
125; PHINODE-LABEL: phiNode2:
126; PHINODE: bf {{r[0-9]}}, .LBB12_3
127; PHINODE: bu .LBB12_1
128; PHINODE-LABEL: .LBB12_1:
129; PHINODE: get r11, id
130; PHINODE-LABEL: .LBB12_2:
131; PHINODE: get r11, id
132; PHINODE: bu .LBB12_2
133; PHINODE-LABEL: .LBB12_3:
134entry:
135  br i1 %bool, label %ConstantExpPhiNode, label %exit
136ConstantExpPhiNode:
137  %ptr = phi i32* [ getelementptr inbounds ([3 x i32], [3 x i32]* @tl, i32 0, i32 0), %entry ],
138                  [ getelementptr inbounds ([3 x i32], [3 x i32]* @tl, i32 0, i32 0), %ConstantExpPhiNode ]
139  br label %ConstantExpPhiNode
140exit:
141  ret void
142}
143
144; CHECK-LABEL: tl:
145; CHECK: .space  96
146