1 ; RUN: llc -verify-machineinstrs -mtriple=i386-linux-gnu %s -o - | FileCheck %s
2 ; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s
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
8 @L = external global i32
9 @M = external global i8
12 ; CHECK-LABEL: plus_one
19 define i1 @plus_one() {
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
38 ; CHECK-LABEL: plus_forty_two
45 define i1 @plus_forty_two() {
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
64 ; CHECK-LABEL: minus_one
71 define i1 @minus_one() {
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
90 ; CHECK-LABEL: minus_forty_two
97 define i1 @minus_forty_two() {
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
116 ; CHECK-LABEL: test_intervening_call:
120 ; CHECK: call{{[lq]}} bar
121 ; CHECK: addb $127, %al
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
138 ; CHECK-LABEL: test_two_live_flags:
142 ; Save result of the first cmpxchg into D.
143 ; CHECK-NEXT: mov{{[lq]}} %[[AX:[er]ax]], %[[D:[re]d[xi]]]
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
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.
156 ; Fallthrough to test the second cmpxchg's result.
157 ; CHECK: testb %al, %al
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
176 ; CHECK-LABEL: asm_clobbering_flags:
181 ; CHECK-NEXT: #NO_APP
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