1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+bmi2,+popcnt,+lzcnt | FileCheck %s 3 declare void @foo(i32) 4 declare void @foo32(i32) 5 declare void @foo64(i64) 6 7 define void @neg(i32 %x) nounwind { 8 ; CHECK-LABEL: neg: 9 ; CHECK: # %bb.0: 10 ; CHECK-NEXT: negl %edi 11 ; CHECK-NEXT: je .LBB0_1 12 ; CHECK-NEXT: # %bb.2: # %bb 13 ; CHECK-NEXT: jmp foo # TAILCALL 14 ; CHECK-NEXT: .LBB0_1: # %return 15 ; CHECK-NEXT: retq 16 %sub = sub i32 0, %x 17 %cmp = icmp eq i32 %sub, 0 18 br i1 %cmp, label %return, label %bb 19 20 bb: 21 tail call void @foo(i32 %sub) 22 br label %return 23 24 return: 25 ret void 26 } 27 28 define void @sar(i32 %x) nounwind { 29 ; CHECK-LABEL: sar: 30 ; CHECK: # %bb.0: 31 ; CHECK-NEXT: sarl %edi 32 ; CHECK-NEXT: je .LBB1_1 33 ; CHECK-NEXT: # %bb.2: # %bb 34 ; CHECK-NEXT: jmp foo # TAILCALL 35 ; CHECK-NEXT: .LBB1_1: # %return 36 ; CHECK-NEXT: retq 37 %ashr = ashr i32 %x, 1 38 %cmp = icmp eq i32 %ashr, 0 39 br i1 %cmp, label %return, label %bb 40 41 bb: 42 tail call void @foo(i32 %ashr) 43 br label %return 44 45 return: 46 ret void 47 } 48 49 define void @shr(i32 %x) nounwind { 50 ; CHECK-LABEL: shr: 51 ; CHECK: # %bb.0: 52 ; CHECK-NEXT: shrl %edi 53 ; CHECK-NEXT: je .LBB2_1 54 ; CHECK-NEXT: # %bb.2: # %bb 55 ; CHECK-NEXT: jmp foo # TAILCALL 56 ; CHECK-NEXT: .LBB2_1: # %return 57 ; CHECK-NEXT: retq 58 %ashr = lshr i32 %x, 1 59 %cmp = icmp eq i32 %ashr, 0 60 br i1 %cmp, label %return, label %bb 61 62 bb: 63 tail call void @foo(i32 %ashr) 64 br label %return 65 66 return: 67 ret void 68 } 69 70 define void @shri(i32 %x) nounwind { 71 ; CHECK-LABEL: shri: 72 ; CHECK: # %bb.0: 73 ; CHECK-NEXT: shrl $3, %edi 74 ; CHECK-NEXT: je .LBB3_1 75 ; CHECK-NEXT: # %bb.2: # %bb 76 ; CHECK-NEXT: jmp foo # TAILCALL 77 ; CHECK-NEXT: .LBB3_1: # %return 78 ; CHECK-NEXT: retq 79 %ashr = lshr i32 %x, 3 80 %cmp = icmp eq i32 %ashr, 0 81 br i1 %cmp, label %return, label %bb 82 83 bb: 84 tail call void @foo(i32 %ashr) 85 br label %return 86 87 return: 88 ret void 89 } 90 91 define void @shl(i32 %x) nounwind { 92 ; CHECK-LABEL: shl: 93 ; CHECK: # %bb.0: 94 ; CHECK-NEXT: addl %edi, %edi 95 ; CHECK-NEXT: je .LBB4_1 96 ; CHECK-NEXT: # %bb.2: # %bb 97 ; CHECK-NEXT: jmp foo # TAILCALL 98 ; CHECK-NEXT: .LBB4_1: # %return 99 ; CHECK-NEXT: retq 100 %shl = shl i32 %x, 1 101 %cmp = icmp eq i32 %shl, 0 102 br i1 %cmp, label %return, label %bb 103 104 bb: 105 tail call void @foo(i32 %shl) 106 br label %return 107 108 return: 109 ret void 110 } 111 112 define void @shli(i32 %x) nounwind { 113 ; CHECK-LABEL: shli: 114 ; CHECK: # %bb.0: 115 ; CHECK-NEXT: shll $4, %edi 116 ; CHECK-NEXT: je .LBB5_1 117 ; CHECK-NEXT: # %bb.2: # %bb 118 ; CHECK-NEXT: jmp foo # TAILCALL 119 ; CHECK-NEXT: .LBB5_1: # %return 120 ; CHECK-NEXT: retq 121 %shl = shl i32 %x, 4 122 %cmp = icmp eq i32 %shl, 0 123 br i1 %cmp, label %return, label %bb 124 125 bb: 126 tail call void @foo(i32 %shl) 127 br label %return 128 129 return: 130 ret void 131 } 132 133 define zeroext i1 @adc(i128 %x) nounwind { 134 ; CHECK-LABEL: adc: 135 ; CHECK: # %bb.0: 136 ; CHECK-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 137 ; CHECK-NEXT: addq %rdi, %rax 138 ; CHECK-NEXT: adcq $0, %rsi 139 ; CHECK-NEXT: sete %al 140 ; CHECK-NEXT: retq 141 %add = add i128 %x, 9223372036854775808 142 %cmp = icmp ult i128 %add, 18446744073709551616 143 ret i1 %cmp 144 } 145 146 define zeroext i1 @sbb(i128 %x, i128 %y) nounwind { 147 ; CHECK-LABEL: sbb: 148 ; CHECK: # %bb.0: 149 ; CHECK-NEXT: cmpq %rdx, %rdi 150 ; CHECK-NEXT: sbbq %rcx, %rsi 151 ; CHECK-NEXT: setns %al 152 ; CHECK-NEXT: retq 153 %sub = sub i128 %x, %y 154 %cmp = icmp sge i128 %sub, 0 155 ret i1 %cmp 156 } 157 158 define void @andn(i32 %x, i32 %y) nounwind { 159 ; CHECK-LABEL: andn: 160 ; CHECK: # %bb.0: 161 ; CHECK-NEXT: andnl %esi, %edi, %edi 162 ; CHECK-NEXT: je .LBB8_1 163 ; CHECK-NEXT: # %bb.2: # %bb 164 ; CHECK-NEXT: jmp foo # TAILCALL 165 ; CHECK-NEXT: .LBB8_1: # %return 166 ; CHECK-NEXT: retq 167 %not = xor i32 %x, -1 168 %andn = and i32 %y, %not 169 %cmp = icmp eq i32 %andn, 0 170 br i1 %cmp, label %return, label %bb 171 172 bb: 173 tail call void @foo(i32 %andn) 174 br label %return 175 176 return: 177 ret void 178 } 179 180 declare i32 @llvm.x86.bmi.bextr.32(i32, i32) nounwind readnone 181 define void @bextr(i32 %x, i32 %y) nounwind { 182 ; CHECK-LABEL: bextr: 183 ; CHECK: # %bb.0: 184 ; CHECK-NEXT: bextrl %esi, %edi, %edi 185 ; CHECK-NEXT: je .LBB9_1 186 ; CHECK-NEXT: # %bb.2: # %bb 187 ; CHECK-NEXT: jmp foo # TAILCALL 188 ; CHECK-NEXT: .LBB9_1: # %return 189 ; CHECK-NEXT: retq 190 %bextr = tail call i32 @llvm.x86.bmi.bextr.32(i32 %x, i32 %y) 191 %cmp = icmp eq i32 %bextr, 0 192 br i1 %cmp, label %return, label %bb 193 194 bb: 195 tail call void @foo(i32 %bextr) 196 br label %return 197 198 return: 199 ret void 200 } 201 202 declare i32 @llvm.ctpop.i32(i32) nounwind readnone 203 define void @popcnt(i32 %x) nounwind { 204 ; CHECK-LABEL: popcnt: 205 ; CHECK: # %bb.0: 206 ; CHECK-NEXT: popcntl %edi, %edi 207 ; CHECK-NEXT: je .LBB10_1 208 ; CHECK-NEXT: # %bb.2: # %bb 209 ; CHECK-NEXT: jmp foo # TAILCALL 210 ; CHECK-NEXT: .LBB10_1: # %return 211 ; CHECK-NEXT: retq 212 %popcnt = tail call i32 @llvm.ctpop.i32(i32 %x) 213 %cmp = icmp eq i32 %popcnt, 0 214 br i1 %cmp, label %return, label %bb 215 bb: 216 tail call void @foo(i32 %popcnt) 217 br label %return 218 return: 219 ret void 220 } 221 222 declare i64 @llvm.cttz.i64(i64, i1) 223 define i64 @testCTZ(i64 %v) nounwind { 224 ; CHECK-LABEL: testCTZ: 225 ; CHECK: # %bb.0: 226 ; CHECK-NEXT: tzcntq %rdi, %rcx 227 ; CHECK-NEXT: movl $255, %eax 228 ; CHECK-NEXT: cmovaeq %rcx, %rax 229 ; CHECK-NEXT: retq 230 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 231 %tobool = icmp eq i64 %v, 0 232 %cond = select i1 %tobool, i64 255, i64 %cnt 233 ret i64 %cond 234 } 235 236 declare i32 @llvm.cttz.i32(i32, i1) 237 define void @testCTZ2(i32 %v) nounwind { 238 ; CHECK-LABEL: testCTZ2: 239 ; CHECK: # %bb.0: 240 ; CHECK-NEXT: pushq %rbx 241 ; CHECK-NEXT: tzcntl %edi, %ebx 242 ; CHECK-NEXT: jb .LBB12_2 243 ; CHECK-NEXT: # %bb.1: # %bb 244 ; CHECK-NEXT: movl %ebx, %edi 245 ; CHECK-NEXT: callq foo 246 ; CHECK-NEXT: .LBB12_2: # %return 247 ; CHECK-NEXT: movl %ebx, %edi 248 ; CHECK-NEXT: popq %rbx 249 ; CHECK-NEXT: jmp foo32 # TAILCALL 250 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 251 %cmp = icmp eq i32 %v, 0 252 br i1 %cmp, label %return, label %bb 253 254 bb: 255 tail call void @foo(i32 %cnt) 256 br label %return 257 258 return: 259 tail call void @foo32(i32 %cnt) 260 ret void 261 } 262 263 define void @testCTZ3(i32 %v) nounwind { 264 ; CHECK-LABEL: testCTZ3: 265 ; CHECK: # %bb.0: 266 ; CHECK-NEXT: pushq %rbx 267 ; CHECK-NEXT: tzcntl %edi, %ebx 268 ; CHECK-NEXT: jae .LBB13_2 269 ; CHECK-NEXT: # %bb.1: # %bb 270 ; CHECK-NEXT: movl %ebx, %edi 271 ; CHECK-NEXT: callq foo 272 ; CHECK-NEXT: .LBB13_2: # %return 273 ; CHECK-NEXT: movl %ebx, %edi 274 ; CHECK-NEXT: popq %rbx 275 ; CHECK-NEXT: jmp foo32 # TAILCALL 276 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 277 %cmp = icmp ne i32 %v, 0 278 br i1 %cmp, label %return, label %bb 279 280 bb: 281 tail call void @foo(i32 %cnt) 282 br label %return 283 284 return: 285 tail call void @foo32(i32 %cnt) 286 ret void 287 } 288 289 declare i64 @llvm.ctlz.i64(i64, i1) 290 define i64 @testCLZ(i64 %v) nounwind { 291 ; CHECK-LABEL: testCLZ: 292 ; CHECK: # %bb.0: 293 ; CHECK-NEXT: lzcntq %rdi, %rcx 294 ; CHECK-NEXT: movl $255, %eax 295 ; CHECK-NEXT: cmovaeq %rcx, %rax 296 ; CHECK-NEXT: retq 297 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 298 %tobool = icmp ne i64 %v, 0 299 %cond = select i1 %tobool, i64 %cnt, i64 255 300 ret i64 %cond 301 } 302 303 declare i64 @llvm.ctpop.i64(i64) 304 define i64 @testPOPCNT(i64 %v) nounwind { 305 ; CHECK-LABEL: testPOPCNT: 306 ; CHECK: # %bb.0: 307 ; CHECK-NEXT: popcntq %rdi, %rcx 308 ; CHECK-NEXT: movl $255, %eax 309 ; CHECK-NEXT: cmovneq %rcx, %rax 310 ; CHECK-NEXT: retq 311 %cnt = tail call i64 @llvm.ctpop.i64(i64 %v) 312 %tobool = icmp ne i64 %v, 0 313 %cond = select i1 %tobool, i64 %cnt, i64 255 314 ret i64 %cond 315 } 316