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