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 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 10declare 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 19define i1 @plus_one() { 20entry: 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 31exit: 32 ret i1 true 33 34exit2: 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, 45define i1 @plus_forty_two() { 46entry: 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 57exit: 58 ret i1 true 59 60exit2: 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 71define i1 @minus_one() { 72entry: 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 83exit: 84 ret i1 true 85 86exit2: 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, 97define i1 @minus_forty_two() { 98entry: 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 109exit: 110 ret i1 true 111 112exit2: 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 123define 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 131t: 132 ret i64 42 133 134f: 135 ret i64 0 136} 137 138; CHECK-LABEL: test_two_live_flags: 139; CHECK: cmpxchg 140; CHECK: 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 159define 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 169t: 170 ret i64 42 171 172f: 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 184define 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} 191