438bf8ddf4c707a50cd94e7cec2a4b3d4df00183
[oota-llvm.git] / test / CodeGen / X86 / peephole-na-phys-copy-folding.ll
1 ; RUN: llc -verify-machineinstrs -mtriple=i386-linux-gnu %s -o - | FileCheck %s
2 ; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s
3
4 ; The peephole optimizer can elide some physical register copies such as
5 ; EFLAGS. Make sure the flags are used directly, instead of needlessly using
6 ; lahf, when possible.
7
8 @L = external global i32
9 @M = external global i8
10 declare i32 @bar(i64)
11
12 ; CHECK-LABEL: plus_one
13 ; CHECK-NOT: seto
14 ; CHECK-NOT: lahf
15 ; CHECK-NOT: sahf
16 ; CHECK-NOT: pushf
17 ; CHECK-NOT: popf
18 ; CHECK: incl L
19 define i1 @plus_one() {
20 entry:
21   %loaded_L = load i32, i32* @L
22   %val = add nsw i32 %loaded_L, 1 ; N.B. will emit inc.
23   store i32 %val, i32* @L
24   %loaded_M = load i8, i8* @M
25   %masked = and i8 %loaded_M, 8
26   %M_is_true = icmp ne i8 %masked, 0
27   %L_is_false = icmp eq i32 %val, 0
28   %cond = and i1 %L_is_false, %M_is_true
29   br i1 %cond, label %exit2, label %exit
30
31 exit:
32   ret i1 true
33
34 exit2:
35   ret i1 false
36 }
37
38 ; CHECK-LABEL: plus_forty_two
39 ; CHECK-NOT: seto
40 ; CHECK-NOT: lahf
41 ; CHECK-NOT: sahf
42 ; CHECK-NOT: pushf
43 ; CHECK-NOT: popf
44 ; CHECK: addl $42,
45 define i1 @plus_forty_two() {
46 entry:
47   %loaded_L = load i32, i32* @L
48   %val = add nsw i32 %loaded_L, 42 ; N.B. won't emit inc.
49   store i32 %val, i32* @L
50   %loaded_M = load i8, i8* @M
51   %masked = and i8 %loaded_M, 8
52   %M_is_true = icmp ne i8 %masked, 0
53   %L_is_false = icmp eq i32 %val, 0
54   %cond = and i1 %L_is_false, %M_is_true
55   br i1 %cond, label %exit2, label %exit
56
57 exit:
58   ret i1 true
59
60 exit2:
61   ret i1 false
62 }
63
64 ; CHECK-LABEL: minus_one
65 ; CHECK-NOT: seto
66 ; CHECK-NOT: lahf
67 ; CHECK-NOT: sahf
68 ; CHECK-NOT: pushf
69 ; CHECK-NOT: popf
70 ; CHECK: decl L
71 define i1 @minus_one() {
72 entry:
73   %loaded_L = load i32, i32* @L
74   %val = add nsw i32 %loaded_L, -1 ; N.B. will emit dec.
75   store i32 %val, i32* @L
76   %loaded_M = load i8, i8* @M
77   %masked = and i8 %loaded_M, 8
78   %M_is_true = icmp ne i8 %masked, 0
79   %L_is_false = icmp eq i32 %val, 0
80   %cond = and i1 %L_is_false, %M_is_true
81   br i1 %cond, label %exit2, label %exit
82
83 exit:
84   ret i1 true
85
86 exit2:
87   ret i1 false
88 }
89
90 ; CHECK-LABEL: minus_forty_two
91 ; CHECK-NOT: seto
92 ; CHECK-NOT: lahf
93 ; CHECK-NOT: sahf
94 ; CHECK-NOT: pushf
95 ; CHECK-NOT: popf
96 ; CHECK: addl $-42,
97 define i1 @minus_forty_two() {
98 entry:
99   %loaded_L = load i32, i32* @L
100   %val = add nsw i32 %loaded_L, -42 ; N.B. won't emit dec.
101   store i32 %val, i32* @L
102   %loaded_M = load i8, i8* @M
103   %masked = and i8 %loaded_M, 8
104   %M_is_true = icmp ne i8 %masked, 0
105   %L_is_false = icmp eq i32 %val, 0
106   %cond = and i1 %L_is_false, %M_is_true
107   br i1 %cond, label %exit2, label %exit
108
109 exit:
110   ret i1 true
111
112 exit2:
113   ret i1 false
114 }
115
116 ; CHECK-LABEL: test_intervening_call:
117 ; CHECK:       cmpxchg
118 ; CHECK:       seto %al
119 ; CHECK-NEXT:  lahf
120 ; CHECK:       call{{[lq]}} bar
121 ; CHECK:       addb $127, %al
122 ; CHECK-NEXT:  sahf
123 define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) {
124   ; cmpxchg sets EFLAGS, call clobbers it, then br uses EFLAGS.
125   %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
126   %v = extractvalue { i64, i1 } %cx, 0
127   %p = extractvalue { i64, i1 } %cx, 1
128   call i32 @bar(i64 %v)
129   br i1 %p, label %t, label %f
130
131 t:
132   ret i64 42
133
134 f:
135   ret i64 0
136 }
137
138 ; CHECK-LABEL: test_two_live_flags:
139 ; CHECK:       cmpxchg
140 ; CHECK-NEXT:  seto %al
141 ; CHECK-NEXT:  lahf
142 ; Save result of the first cmpxchg into D.
143 ; CHECK-NEXT:  mov{{[lq]}} %[[AX:[er]ax]], %[[D:[re]d[xi]]]
144 ; CHECK:       cmpxchg
145 ; CHECK-NEXT:  sete %al
146 ; Save result of the second cmpxchg onto the stack.
147 ; CHECK-NEXT:  push{{[lq]}} %[[AX]]
148 ; Restore result of the first cmpxchg from D, put it back in EFLAGS.
149 ; CHECK-NEXT:  mov{{[lq]}} %[[D]], %[[AX]]
150 ; CHECK-NEXT:  addb $127, %al
151 ; CHECK-NEXT:  sahf
152 ; Restore result of the second cmpxchg from the stack.
153 ; CHECK-NEXT:  pop{{[lq]}} %[[AX]]
154 ; Test from EFLAGS restored from first cmpxchg, jump if that fails.
155 ; CHECK-NEXT:  jne
156 ; Fallthrough to test the second cmpxchg's result.
157 ; CHECK:       testb %al, %al
158 ; CHECK-NEXT:  je
159 define i64 @test_two_live_flags(
160        i64* %foo0, i64 %bar0, i64 %baz0,
161        i64* %foo1, i64 %bar1, i64 %baz1) {
162   %cx0 = cmpxchg i64* %foo0, i64 %bar0, i64 %baz0 seq_cst seq_cst
163   %p0 = extractvalue { i64, i1 } %cx0, 1
164   %cx1 = cmpxchg i64* %foo1, i64 %bar1, i64 %baz1 seq_cst seq_cst
165   %p1 = extractvalue { i64, i1 } %cx1, 1
166   %flag = and i1 %p0, %p1
167   br i1 %flag, label %t, label %f
168
169 t:
170   ret i64 42
171
172 f:
173   ret i64 0
174 }
175
176 ; CHECK-LABEL: asm_clobbering_flags:
177 ; CHECK:       test
178 ; CHECK-NEXT:  setg
179 ; CHECK-NEXT:  #APP
180 ; CHECK-NEXT:  bsfl
181 ; CHECK-NEXT:  #NO_APP
182 ; CHECK-NEXT:  movl
183 ; CHECK-NEXT:  ret
184 define i1 @asm_clobbering_flags(i32* %mem) {
185   %val = load i32, i32* %mem, align 4
186   %cmp = icmp sgt i32 %val, 0
187   %res = tail call i32 asm "bsfl $1,$0", "=r,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %val)
188   store i32 %res, i32* %mem, align 4
189   ret i1 %cmp
190 }