1; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s -check-prefix=i386 2; RUN: llc -mtriple=i386-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=i386f 3 4; RUN: llc -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s -check-prefix=x8664 5; RUN: llc -mtriple=x86_64-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664 6; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s -check-prefix=x8664-sahf 7; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664-sahf 8; RUN: llc -mtriple=x86_64-linux-gnu -mcpu=corei7 %s -o - | FileCheck %s -check-prefix=x8664-sahf 9 10; TODO: Reenable verify-machineinstr once the if (!AXDead) // FIXME 11; in X86InstrInfo::copyPhysReg() is resolved. 12 13declare i32 @foo() 14declare i32 @bar(i64) 15 16define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) { 17; i386-LABEL: test_intervening_call: 18; i386: cmpxchg8b 19; i386-NEXT: pushl %eax 20; i386-NEXT: seto %al 21; i386-NEXT: lahf 22; i386-NEXT: movl %eax, [[FLAGS:%.*]] 23; i386-NEXT: popl %eax 24; i386-NEXT: subl $8, %esp 25; i386-NEXT: pushl %edx 26; i386-NEXT: pushl %eax 27; i386-NEXT: calll bar 28; i386-NEXT: addl $16, %esp 29; i386-NEXT: movl [[FLAGS]], %eax 30; i386-NEXT: addb $127, %al 31; i386-NEXT: sahf 32; i386-NEXT: jne 33 34; i386f-LABEL: test_intervening_call: 35; i386f: cmpxchg8b 36; i386f-NEXT: movl %eax, (%esp) 37; i386f-NEXT: movl %edx, 4(%esp) 38; i386f-NEXT: seto %al 39; i386f-NEXT: lahf 40; i386f-NEXT: movl %eax, [[FLAGS:%.*]] 41; i386f-NEXT: calll bar 42; i386f-NEXT: movl [[FLAGS]], %eax 43; i386f-NEXT: addb $127, %al 44; i386f-NEXT: sahf 45; i386f-NEXT: jne 46 47; x8664-LABEL: test_intervening_call: 48; x8664: cmpxchgq 49; x8664: pushfq 50; x8664-NEXT: popq [[FLAGS:%.*]] 51; x8664-NEXT: movq %rax, %rdi 52; x8664-NEXT: callq bar 53; x8664-NEXT: pushq [[FLAGS]] 54; x8664-NEXT: popfq 55; x8664-NEXT: jne 56 57; x8664-sahf-LABEL: test_intervening_call: 58; x8664-sahf: cmpxchgq 59; x8664-sahf: pushq %rax 60; x8664-sahf-NEXT: seto %al 61; x8664-sahf-NEXT: lahf 62; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]] 63; x8664-sahf-NEXT: popq %rax 64; x8664-sahf-NEXT: movq %rax, %rdi 65; x8664-sahf-NEXT: callq bar 66; RAX is dead, no need to push and pop it. 67; x8664-sahf-NEXT: movq [[FLAGS]], %rax 68; x8664-sahf-NEXT: addb $127, %al 69; x8664-sahf-NEXT: sahf 70; x8664-sahf-NEXT: jne 71 72 %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst 73 %v = extractvalue { i64, i1 } %cx, 0 74 %p = extractvalue { i64, i1 } %cx, 1 75 call i32 @bar(i64 %v) 76 br i1 %p, label %t, label %f 77 78t: 79 ret i64 42 80 81f: 82 ret i64 0 83} 84 85; Interesting in producing a clobber without any function calls. 86define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) { 87; i386-LABEL: test_control_flow: 88; i386: cmpxchg 89; i386-NEXT: jne 90 91; i386f-LABEL: test_control_flow: 92; i386f: cmpxchg 93; i386f-NEXT: jne 94 95; x8664-LABEL: test_control_flow: 96; x8664: cmpxchg 97; x8664-NEXT: jne 98 99; x8664-sahf-LABEL: test_control_flow: 100; x8664-sahf: cmpxchg 101; x8664-sahf-NEXT: jne 102 103entry: 104 %cmp = icmp sgt i32 %i, %j 105 br i1 %cmp, label %loop_start, label %cond.end 106 107loop_start: 108 br label %while.condthread-pre-split.i 109 110while.condthread-pre-split.i: 111 %.pr.i = load i32, i32* %p, align 4 112 br label %while.cond.i 113 114while.cond.i: 115 %0 = phi i32 [ %.pr.i, %while.condthread-pre-split.i ], [ 0, %while.cond.i ] 116 %tobool.i = icmp eq i32 %0, 0 117 br i1 %tobool.i, label %while.cond.i, label %while.body.i 118 119while.body.i: 120 %.lcssa = phi i32 [ %0, %while.cond.i ] 121 %1 = cmpxchg i32* %p, i32 %.lcssa, i32 %.lcssa seq_cst seq_cst 122 %2 = extractvalue { i32, i1 } %1, 1 123 br i1 %2, label %cond.end.loopexit, label %while.condthread-pre-split.i 124 125cond.end.loopexit: 126 br label %cond.end 127 128cond.end: 129 %cond = phi i32 [ %i, %entry ], [ 0, %cond.end.loopexit ] 130 ret i32 %cond 131} 132 133; This one is an interesting case because CMOV doesn't have a chain 134; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here. 135define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) { 136; i386-LABEL: test_feed_cmov: 137; i386: cmpxchgl 138; i386-NEXT: seto %al 139; i386-NEXT: lahf 140; i386-NEXT: movl %eax, [[FLAGS:%.*]] 141; i386-NEXT: calll foo 142; i386-NEXT: pushl %eax 143; i386-NEXT: movl [[FLAGS]], %eax 144; i386-NEXT: addb $127, %al 145; i386-NEXT: sahf 146; i386-NEXT: popl %eax 147 148; i386f-LABEL: test_feed_cmov: 149; i386f: cmpxchgl 150; i386f-NEXT: seto %al 151; i386f-NEXT: lahf 152; i386f-NEXT: movl %eax, [[FLAGS:%.*]] 153; i386f-NEXT: calll foo 154; i386f-NEXT: pushl %eax 155; i386f-NEXT: movl [[FLAGS]], %eax 156; i386f-NEXT: addb $127, %al 157; i386f-NEXT: sahf 158; i386f-NEXT: popl %eax 159 160; x8664-LABEL: test_feed_cmov: 161; x8664: cmpxchg 162; x8664: pushfq 163; x8664-NEXT: popq [[FLAGS:%.*]] 164; x8664-NEXT: callq foo 165; x8664-NEXT: pushq [[FLAGS]] 166; x8664-NEXT: popfq 167 168; x8664-sahf-LABEL: test_feed_cmov: 169; x8664-sahf: cmpxchgl 170; RAX is dead, do not push or pop it. 171; x8664-sahf-NEXT: seto %al 172; x8664-sahf-NEXT: lahf 173; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]] 174; x8664-sahf-NEXT: callq foo 175; x8664-sahf-NEXT: pushq %rax 176; x8664-sahf-NEXT: movq [[FLAGS]], %rax 177; x8664-sahf-NEXT: addb $127, %al 178; x8664-sahf-NEXT: sahf 179; x8664-sahf-NEXT: popq %rax 180 181 %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst 182 %success = extractvalue { i32, i1 } %res, 1 183 184 %rhs = call i32 @foo() 185 186 %ret = select i1 %success, i32 %new, i32 %rhs 187 ret i32 %ret 188} 189