[ARM] When a bitcast is about to be turned into a VMOVDRR, try to combine it
[oota-llvm.git] / test / CodeGen / ARM / returned-ext.ll
1 ; RUN: llc < %s -mtriple=armv6-linux-gnueabi | FileCheck %s -check-prefix=CHECKELF
2 ; RUN: llc < %s -mtriple=thumbv7-apple-ios5.0 | FileCheck %s -check-prefix=CHECKT2D
3
4 declare i16 @identity16(i16 returned %x)
5 declare i32 @identity32(i32 returned %x)
6 declare zeroext i16 @retzext16(i16 returned %x)
7 declare i16 @paramzext16(i16 zeroext returned %x)
8 declare zeroext i16 @bothzext16(i16 zeroext returned %x)
9
10 ; The zeroext param attribute below is meant to have no effect
11 define i16 @test_identity(i16 zeroext %x) {
12 entry:
13 ; CHECKELF-LABEL: test_identity:
14 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
15 ; CHECKELF: bl identity16
16 ; CHECKELF: uxth r0, r0
17 ; CHECKELF: bl identity32
18 ; CHECKELF: mov r0, [[SAVEX]]
19 ; CHECKT2D-LABEL: test_identity:
20 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
21 ; CHECKT2D: blx _identity16
22 ; CHECKT2D: uxth r0, r0
23 ; CHECKT2D: blx _identity32
24 ; CHECKT2D: mov r0, [[SAVEX]]
25   %call = tail call i16 @identity16(i16 %x)
26   %b = zext i16 %call to i32
27   %call2 = tail call i32 @identity32(i32 %b)
28   ret i16 %x
29 }
30
31 ; FIXME: This ought not to require register saving but currently does because
32 ; x is not considered equal to %call (see SelectionDAGBuilder.cpp)
33 define i16 @test_matched_ret(i16 %x) {
34 entry:
35 ; CHECKELF-LABEL: test_matched_ret:
36
37 ; This shouldn't be required
38 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
39
40 ; CHECKELF: bl retzext16
41 ; CHECKELF-NOT: uxth r0, {{r[0-9]+}}
42 ; CHECKELF: bl identity32
43
44 ; This shouldn't be required
45 ; CHECKELF: mov r0, [[SAVEX]]
46
47 ; CHECKT2D-LABEL: test_matched_ret:
48
49 ; This shouldn't be required
50 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
51
52 ; CHECKT2D: blx _retzext16
53 ; CHECKT2D-NOT: uxth r0, {{r[0-9]+}}
54 ; CHECKT2D: blx _identity32
55
56 ; This shouldn't be required
57 ; CHECKT2D: mov r0, [[SAVEX]]
58
59   %call = tail call i16 @retzext16(i16 %x)
60   %b = zext i16 %call to i32
61   %call2 = tail call i32 @identity32(i32 %b)
62   ret i16 %x
63 }
64
65 define i16 @test_mismatched_ret(i16 %x) {
66 entry:
67 ; CHECKELF-LABEL: test_mismatched_ret:
68 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
69 ; CHECKELF: bl retzext16
70 ; CHECKELF: sxth r0, {{r[0-9]+}}
71 ; CHECKELF: bl identity32
72 ; CHECKELF: mov r0, [[SAVEX]]
73 ; CHECKT2D-LABEL: test_mismatched_ret:
74 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
75 ; CHECKT2D: blx _retzext16
76 ; CHECKT2D: sxth r0, {{r[0-9]+}}
77 ; CHECKT2D: blx _identity32
78 ; CHECKT2D: mov r0, [[SAVEX]]
79   %call = tail call i16 @retzext16(i16 %x)
80   %b = sext i16 %call to i32
81   %call2 = tail call i32 @identity32(i32 %b)
82   ret i16 %x
83 }
84
85 define i16 @test_matched_paramext(i16 %x) {
86 entry:
87 ; CHECKELF-LABEL: test_matched_paramext:
88 ; CHECKELF: uxth r0, r0
89 ; CHECKELF: bl paramzext16
90 ; CHECKELF: uxth r0, r0
91 ; CHECKELF: bl identity32
92 ; CHECKELF: b paramzext16
93 ; CHECKT2D-LABEL: test_matched_paramext:
94 ; CHECKT2D: uxth r0, r0
95 ; CHECKT2D: blx _paramzext16
96 ; CHECKT2D: uxth r0, r0
97 ; CHECKT2D: blx _identity32
98 ; CHECKT2D: b.w _paramzext16
99   %call = tail call i16 @paramzext16(i16 %x)
100   %b = zext i16 %call to i32
101   %call2 = tail call i32 @identity32(i32 %b)
102   %call3 = tail call i16 @paramzext16(i16 %call)
103   ret i16 %call3
104 }
105
106 ; FIXME: This theoretically ought to optimize to exact same output as the
107 ; version above, but doesn't currently (see SelectionDAGBuilder.cpp) 
108 define i16 @test_matched_paramext2(i16 %x) {
109 entry:
110
111 ; Since there doesn't seem to be an unambiguous optimal selection and
112 ; scheduling of uxth and mov instructions below in lieu of the 'returned'
113 ; optimization, don't bother checking: just verify that the calls are made
114 ; in the correct order as a basic sanity check
115
116 ; CHECKELF-LABEL: test_matched_paramext2:
117 ; CHECKELF: bl paramzext16
118 ; CHECKELF: bl identity32
119 ; CHECKELF: b paramzext16
120 ; CHECKT2D-LABEL: test_matched_paramext2:
121 ; CHECKT2D: blx _paramzext16
122 ; CHECKT2D: blx _identity32
123 ; CHECKT2D: b.w _paramzext16
124   %call = tail call i16 @paramzext16(i16 %x)
125
126 ; Should make no difference if %x is used below rather than %call, but it does
127   %b = zext i16 %x to i32
128
129   %call2 = tail call i32 @identity32(i32 %b)
130   %call3 = tail call i16 @paramzext16(i16 %call)
131   ret i16 %call3
132 }
133
134 define i16 @test_matched_bothext(i16 %x) {
135 entry:
136 ; CHECKELF-LABEL: test_matched_bothext:
137 ; CHECKELF: uxth r0, r0
138 ; CHECKELF: bl bothzext16
139 ; CHECKELF-NOT: uxth r0, r0
140
141 ; FIXME: Tail call should be OK here
142 ; CHECKELF: bl identity32
143
144 ; CHECKT2D-LABEL: test_matched_bothext:
145 ; CHECKT2D: uxth r0, r0
146 ; CHECKT2D: blx _bothzext16
147 ; CHECKT2D-NOT: uxth r0, r0
148
149 ; FIXME: Tail call should be OK here
150 ; CHECKT2D: blx _identity32
151
152   %call = tail call i16 @bothzext16(i16 %x)
153   %b = zext i16 %x to i32
154   %call2 = tail call i32 @identity32(i32 %b)
155   ret i16 %call
156 }
157
158 define i16 @test_mismatched_bothext(i16 %x) {
159 entry:
160 ; CHECKELF-LABEL: test_mismatched_bothext:
161 ; CHECKELF: mov [[SAVEX:r[0-9]+]], r0
162 ; CHECKELF: uxth r0, {{r[0-9]+}}
163 ; CHECKELF: bl bothzext16
164 ; CHECKELF: sxth r0, [[SAVEX]]
165 ; CHECKELF: bl identity32
166 ; CHECKELF: mov r0, [[SAVEX]]
167 ; CHECKT2D-LABEL: test_mismatched_bothext:
168 ; CHECKT2D: mov [[SAVEX:r[0-9]+]], r0
169 ; CHECKT2D: uxth r0, {{r[0-9]+}}
170 ; CHECKT2D: blx _bothzext16
171 ; CHECKT2D: sxth r0, [[SAVEX]]
172 ; CHECKT2D: blx _identity32
173 ; CHECKT2D: mov r0, [[SAVEX]]
174   %call = tail call i16 @bothzext16(i16 %x)
175   %b = sext i16 %x to i32
176   %call2 = tail call i32 @identity32(i32 %b)
177   ret i16 %x
178 }