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