1 ; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s
2 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s
4 ; FIXME Add -verify-machineinstrs back when PR24535 is fixed.
6 ; The peephole optimizer can elide some physical register copies such as
7 ; EFLAGS. Make sure the flags are used directly, instead of needlessly using
10 @L = external global i32
11 @M = external global i8
14 ; CHECK-LABEL: plus_one
21 define i1 @plus_one() {
23 %loaded_L = load i32, i32* @L
24 %val = add nsw i32 %loaded_L, 1 ; N.B. will emit inc.
25 store i32 %val, i32* @L
26 %loaded_M = load i8, i8* @M
27 %masked = and i8 %loaded_M, 8
28 %M_is_true = icmp ne i8 %masked, 0
29 %L_is_false = icmp eq i32 %val, 0
30 %cond = and i1 %L_is_false, %M_is_true
31 br i1 %cond, label %exit2, label %exit
40 ; CHECK-LABEL: plus_forty_two
47 define i1 @plus_forty_two() {
49 %loaded_L = load i32, i32* @L
50 %val = add nsw i32 %loaded_L, 42 ; N.B. won't emit inc.
51 store i32 %val, i32* @L
52 %loaded_M = load i8, i8* @M
53 %masked = and i8 %loaded_M, 8
54 %M_is_true = icmp ne i8 %masked, 0
55 %L_is_false = icmp eq i32 %val, 0
56 %cond = and i1 %L_is_false, %M_is_true
57 br i1 %cond, label %exit2, label %exit
66 ; CHECK-LABEL: minus_one
73 define i1 @minus_one() {
75 %loaded_L = load i32, i32* @L
76 %val = add nsw i32 %loaded_L, -1 ; N.B. will emit dec.
77 store i32 %val, i32* @L
78 %loaded_M = load i8, i8* @M
79 %masked = and i8 %loaded_M, 8
80 %M_is_true = icmp ne i8 %masked, 0
81 %L_is_false = icmp eq i32 %val, 0
82 %cond = and i1 %L_is_false, %M_is_true
83 br i1 %cond, label %exit2, label %exit
92 ; CHECK-LABEL: minus_forty_two
99 define i1 @minus_forty_two() {
101 %loaded_L = load i32, i32* @L
102 %val = add nsw i32 %loaded_L, -42 ; N.B. won't emit dec.
103 store i32 %val, i32* @L
104 %loaded_M = load i8, i8* @M
105 %masked = and i8 %loaded_M, 8
106 %M_is_true = icmp ne i8 %masked, 0
107 %L_is_false = icmp eq i32 %val, 0
108 %cond = and i1 %L_is_false, %M_is_true
109 br i1 %cond, label %exit2, label %exit
118 ; CHECK-LABEL: test_intervening_call:
122 ; CHECK: call{{[lq]}} bar
123 ; CHECK: addb $127, %al
125 define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) {
126 ; cmpxchg sets EFLAGS, call clobbers it, then br uses EFLAGS.
127 %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
128 %v = extractvalue { i64, i1 } %cx, 0
129 %p = extractvalue { i64, i1 } %cx, 1
130 call i32 @bar(i64 %v)
131 br i1 %p, label %t, label %f
140 ; CHECK-LABEL: test_two_live_flags:
144 ; Save result of the first cmpxchg into D.
145 ; CHECK-NEXT: mov{{[lq]}} %[[AX:[er]ax]], %[[D:[re]d[xi]]]
147 ; CHECK-NEXT: sete %al
148 ; Save result of the second cmpxchg onto the stack.
149 ; CHECK-NEXT: push{{[lq]}} %[[AX]]
150 ; Restore result of the first cmpxchg from D, put it back in EFLAGS.
151 ; CHECK-NEXT: mov{{[lq]}} %[[D]], %[[AX]]
152 ; CHECK-NEXT: addb $127, %al
154 ; Restore result of the second cmpxchg from the stack.
155 ; CHECK-NEXT: pop{{[lq]}} %[[AX]]
156 ; Test from EFLAGS restored from first cmpxchg, jump if that fails.
158 ; Fallthrough to test the second cmpxchg's result.
159 ; CHECK: testb %al, %al
161 define i64 @test_two_live_flags(
162 i64* %foo0, i64 %bar0, i64 %baz0,
163 i64* %foo1, i64 %bar1, i64 %baz1) {
164 %cx0 = cmpxchg i64* %foo0, i64 %bar0, i64 %baz0 seq_cst seq_cst
165 %p0 = extractvalue { i64, i1 } %cx0, 1
166 %cx1 = cmpxchg i64* %foo1, i64 %bar1, i64 %baz1 seq_cst seq_cst
167 %p1 = extractvalue { i64, i1 } %cx1, 1
168 %flag = and i1 %p0, %p1
169 br i1 %flag, label %t, label %f
178 ; CHECK-LABEL: asm_clobbering_flags:
183 ; CHECK-NEXT: #NO_APP
186 define i1 @asm_clobbering_flags(i32* %mem) {
187 %val = load i32, i32* %mem, align 4
188 %cmp = icmp sgt i32 %val, 0
189 %res = tail call i32 asm "bsfl $1,$0", "=r,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %val)
190 store i32 %res, i32* %mem, align 4