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 13 declare i32 @foo() 14 declare i32 @bar(i64) 15 16 define 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 78 t: 79 ret i64 42 80 81 f: 82 ret i64 0 83 } 84 85 ; Interesting in producing a clobber without any function calls. 86 define 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 103 entry: 104 %cmp = icmp sgt i32 %i, %j 105 br i1 %cmp, label %loop_start, label %cond.end 106 107 loop_start: 108 br label %while.condthread-pre-split.i 109 110 while.condthread-pre-split.i: 111 %.pr.i = load i32, i32* %p, align 4 112 br label %while.cond.i 113 114 while.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 119 while.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 125 cond.end.loopexit: 126 br label %cond.end 127 128 cond.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. 135 define 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