Skip to content

Commit 58fbea2

Browse files
fhahnMingcongBai
authored andcommitted
[Thumb] Add test case where the machine-outliner clobbers LR.
Add ad test case where `bl OUTLINED_FUNCTION_0` clobbers LR, which in turn is used the later call to memcpy to return to the caller. (cherry picked from commit 20f634f)
1 parent 74b42a4 commit 58fbea2

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2+
; RUN: llc -mtriple=thumbv7m-none-none-eabi < %s | FileCheck %s
3+
4+
target datalayout = "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
5+
6+
%struct.wibble = type { [30 x i8], i8, i32 }
7+
%struct.eggs = type { i32, [30 x i8], i8, i8, i8, [3 x i8] }
8+
9+
@global = external global [3 x %struct.wibble], align 4
10+
@global.1 = external global [3 x %struct.wibble], align 4
11+
12+
; Test case to make sure calling an outlined function does not clobber LR used
13+
; by a tail call in caller.
14+
; FIXME: Currently bl OUTLINED_FUNCTION_0 clobbers LR, which in turn is used
15+
; by the later call to memcpy to return to the caller.
16+
define void @test(ptr nocapture noundef writeonly %arg, i32 noundef %arg1, i8 noundef zeroext %arg2) unnamed_addr #0 {
17+
; CHECK-LABEL: test:
18+
; CHECK: @ %bb.0: @ %bb
19+
; CHECK-NEXT: cmp r1, #2
20+
; CHECK-NEXT: beq .LBB0_3
21+
; CHECK-NEXT: @ %bb.1: @ %bb
22+
; CHECK-NEXT: cmp r1, #1
23+
; CHECK-NEXT: bne .LBB0_5
24+
; CHECK-NEXT: @ %bb.2: @ %bb4
25+
; CHECK-NEXT: bl OUTLINED_FUNCTION_0
26+
; CHECK-NEXT: ldr r2, .LCPI0_1
27+
; CHECK-NEXT: b .LBB0_4
28+
; CHECK-NEXT: .LBB0_3: @ %bb14
29+
; CHECK-NEXT: bl OUTLINED_FUNCTION_0
30+
; CHECK-NEXT: ldr r2, .LCPI0_0
31+
; CHECK-NEXT: .LBB0_4: @ %bb4
32+
; CHECK-NEXT: add.w r1, r2, r1, lsl #2
33+
; CHECK-NEXT: adds r0, #4
34+
; CHECK-NEXT: movs r2, #30
35+
; CHECK-NEXT: b __aeabi_memcpy
36+
; CHECK-NEXT: .LBB0_5: @ %bb24
37+
; CHECK-NEXT: .save {r7, lr}
38+
; CHECK-NEXT: push {r7, lr}
39+
; CHECK-NEXT: bl wombat
40+
; CHECK-NEXT: @APP
41+
; CHECK-NEXT: @NO_APP
42+
; CHECK-NEXT: pop {r7, pc}
43+
; CHECK-NEXT: .p2align 2
44+
; CHECK-NEXT: @ %bb.6:
45+
; CHECK-NEXT: .LCPI0_0:
46+
; CHECK-NEXT: .long global.1
47+
; CHECK-NEXT: .LCPI0_1:
48+
; CHECK-NEXT: .long global
49+
bb:
50+
%gep = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 4
51+
%zext = zext i8 %arg2 to i32
52+
switch i32 %arg1, label %bb24 [
53+
i32 1, label %bb4
54+
i32 2, label %bb14
55+
]
56+
57+
bb4: ; preds = %bb3
58+
store i8 1, ptr %gep, align 4, !tbaa !6
59+
%gep5 = getelementptr inbounds [3 x %struct.wibble], ptr @global, i32 0, i32 %zext
60+
%gep6 = getelementptr inbounds [3 x %struct.wibble], ptr @global, i32 0, i32 %zext, i32 2
61+
%load = load i32, ptr %gep6, align 4, !tbaa !11
62+
%gep7 = getelementptr inbounds [3 x %struct.wibble], ptr @global, i32 0, i32 %zext, i32 1
63+
%load8 = load i8, ptr %gep7, align 2, !tbaa !13
64+
%gep9 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 3
65+
%gep10 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 2
66+
store i8 30, ptr %gep10, align 2, !tbaa !16
67+
%gep11 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 1
68+
tail call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(30) %gep11, ptr noundef nonnull align 4 dereferenceable(30) %gep5, i32 30, i1 false)
69+
br label %bb26
70+
71+
bb14: ; preds = %bb12
72+
store i8 1, ptr %gep, align 4, !tbaa !6
73+
%gep16 = getelementptr inbounds [3 x %struct.wibble], ptr @global.1, i32 0, i32 %zext
74+
%gep17 = getelementptr inbounds [3 x %struct.wibble], ptr @global.1, i32 0, i32 %zext, i32 2
75+
%load18 = load i32, ptr %gep17, align 4, !tbaa !21
76+
%gep19 = getelementptr inbounds [3 x %struct.wibble], ptr @global.1, i32 0, i32 %zext, i32 1
77+
%load20 = load i8, ptr %gep19, align 2, !tbaa !23
78+
%gep21 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 3
79+
%gep22 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 2
80+
store i8 30, ptr %gep22, align 2, !tbaa !16
81+
%gep23 = getelementptr inbounds %struct.eggs, ptr %arg, i32 0, i32 1
82+
tail call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(30) %gep23, ptr noundef nonnull align 4 dereferenceable(30) %gep16, i32 30, i1 false)
83+
br label %bb26
84+
85+
bb24: ; preds = %bb
86+
tail call void @wombat()
87+
tail call void asm sideeffect "", ""()
88+
br label %bb26
89+
90+
bb26: ; preds = %bb24, %bb14, %bb12, %bb4, %bb3
91+
ret void
92+
}
93+
94+
declare void @wombat()
95+
96+
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2
97+
98+
attributes #0 = { minsize noimplicitfloat nounwind optsize }
99+
100+
!6 = !{!7, !9, i64 36}
101+
!7 = !{!"", !8, i64 0, !9, i64 4, !9, i64 34, !9, i64 35, !9, i64 36, !9, i64 37}
102+
!8 = !{!"long", !9, i64 0}
103+
!9 = !{!"omnipotent char", !10, i64 0}
104+
!10 = !{!"Simple C/C++ TBAA"}
105+
!11 = !{!12, !8, i64 32}
106+
!12 = !{!"B", !9, i64 0, !9, i64 30, !8, i64 32}
107+
!13 = !{!12, !9, i64 30}
108+
!14 = !{!7, !8, i64 0}
109+
!15 = !{!7, !9, i64 35}
110+
!16 = !{!7, !9, i64 34}
111+
!21 = !{!22, !8, i64 32}
112+
!22 = !{!"A", !9, i64 0, !9, i64 30, !8, i64 32}
113+
!23 = !{!22, !9, i64 30}

0 commit comments

Comments
 (0)