1 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI 2 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT 3 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC 4 5 6 define i64 @test1(i64 %A) { 7 ; ALL-LABEL: @test1( 8 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 9 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) 10 ; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]] 11 ; ALL: ret 12 entry: 13 %tobool = icmp eq i64 %A, 0 14 br i1 %tobool, label %cond.end, label %cond.true 15 16 cond.true: ; preds = %entry 17 %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) 18 br label %cond.end 19 20 cond.end: ; preds = %entry, %cond.true 21 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] 22 ret i64 %cond 23 } 24 25 define i32 @test2(i32 %A) { 26 ; ALL-LABEL: @test2( 27 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 28 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 29 ; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]] 30 ; ALL: ret 31 entry: 32 %tobool = icmp eq i32 %A, 0 33 br i1 %tobool, label %cond.end, label %cond.true 34 35 cond.true: ; preds = %entry 36 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 37 br label %cond.end 38 39 cond.end: ; preds = %entry, %cond.true 40 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 41 ret i32 %cond 42 } 43 44 45 define signext i16 @test3(i16 signext %A) { 46 ; ALL-LABEL: @test3( 47 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 48 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 49 ; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]] 50 ; ALL: ret 51 entry: 52 %tobool = icmp eq i16 %A, 0 53 br i1 %tobool, label %cond.end, label %cond.true 54 55 cond.true: ; preds = %entry 56 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 57 br label %cond.end 58 59 cond.end: ; preds = %entry, %cond.true 60 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 61 ret i16 %cond 62 } 63 64 65 define i64 @test1b(i64 %A) { 66 ; ALL-LABEL: @test1b( 67 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 68 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 69 ; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]] 70 ; ALL: ret 71 entry: 72 %tobool = icmp eq i64 %A, 0 73 br i1 %tobool, label %cond.end, label %cond.true 74 75 cond.true: ; preds = %entry 76 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 77 br label %cond.end 78 79 cond.end: ; preds = %entry, %cond.true 80 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] 81 ret i64 %cond 82 } 83 84 85 define i32 @test2b(i32 %A) { 86 ; ALL-LABEL: @test2b( 87 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 88 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 89 ; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]] 90 ; ALL: ret 91 entry: 92 %tobool = icmp eq i32 %A, 0 93 br i1 %tobool, label %cond.end, label %cond.true 94 95 cond.true: ; preds = %entry 96 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 97 br label %cond.end 98 99 cond.end: ; preds = %entry, %cond.true 100 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 101 ret i32 %cond 102 } 103 104 105 define signext i16 @test3b(i16 signext %A) { 106 ; ALL-LABEL: @test3b( 107 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 108 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 109 ; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]] 110 ; ALL: ret 111 entry: 112 %tobool = icmp eq i16 %A, 0 113 br i1 %tobool, label %cond.end, label %cond.true 114 115 cond.true: ; preds = %entry 116 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 117 br label %cond.end 118 119 cond.end: ; preds = %entry, %cond.true 120 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 121 ret i16 %cond 122 } 123 124 ; The following tests verify that calls to cttz/ctlz are speculated even if 125 ; basic block %cond.true has an extra zero extend/truncate which is "free" 126 ; for the target. 127 128 define i64 @test1e(i32 %x) { 129 ; ALL-LABEL: @test1e( 130 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 131 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 132 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64 133 ; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] 134 ; LZCNT-NOT: select 135 ; GENERIC-NOT: select 136 ; ALL: ret 137 entry: 138 %tobool = icmp eq i32 %x, 0 139 br i1 %tobool, label %cond.end, label %cond.true 140 141 cond.true: ; preds = %entry 142 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 143 %phitmp2 = zext i32 %0 to i64 144 br label %cond.end 145 146 cond.end: ; preds = %entry, %cond.true 147 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 148 ret i64 %cond 149 } 150 151 define i32 @test2e(i64 %x) { 152 ; ALL-LABEL: @test2e( 153 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 154 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 155 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32 156 ; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] 157 ; LZCNT-NOT: select 158 ; GENERIC-NOT: select 159 ; ALL: ret 160 entry: 161 %tobool = icmp eq i64 %x, 0 162 br i1 %tobool, label %cond.end, label %cond.true 163 164 cond.true: ; preds = %entry 165 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 166 %cast = trunc i64 %0 to i32 167 br label %cond.end 168 169 cond.end: ; preds = %entry, %cond.true 170 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 171 ret i32 %cond 172 } 173 174 define i64 @test3e(i32 %x) { 175 ; ALL-LABEL: @test3e( 176 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 177 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 178 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64 179 ; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] 180 ; BMI-NOT: select 181 ; GENERIC-NOT: select 182 ; ALL: ret 183 entry: 184 %tobool = icmp eq i32 %x, 0 185 br i1 %tobool, label %cond.end, label %cond.true 186 187 cond.true: ; preds = %entry 188 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 189 %phitmp2 = zext i32 %0 to i64 190 br label %cond.end 191 192 cond.end: ; preds = %entry, %cond.true 193 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 194 ret i64 %cond 195 } 196 197 define i32 @test4e(i64 %x) { 198 ; ALL-LABEL: @test4e( 199 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 200 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 201 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32 202 ; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] 203 ; BMI-NOT: select 204 ; GENERIC-NOT: select 205 ; ALL: ret 206 entry: 207 %tobool = icmp eq i64 %x, 0 208 br i1 %tobool, label %cond.end, label %cond.true 209 210 cond.true: ; preds = %entry 211 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 212 %cast = trunc i64 %0 to i32 213 br label %cond.end 214 215 cond.end: ; preds = %entry, %cond.true 216 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 217 ret i32 %cond 218 } 219 220 define i16 @test5e(i64 %x) { 221 ; ALL-LABEL: @test5e( 222 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 223 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 224 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16 225 ; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] 226 ; BMI-NOT: select 227 ; GENERIC-NOT: select 228 ; ALL: ret 229 entry: 230 %tobool = icmp eq i64 %x, 0 231 br i1 %tobool, label %cond.end, label %cond.true 232 233 cond.true: ; preds = %entry 234 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 235 %cast = trunc i64 %0 to i16 236 br label %cond.end 237 238 cond.end: ; preds = %entry, %cond.true 239 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 240 ret i16 %cond 241 } 242 243 define i16 @test6e(i32 %x) { 244 ; ALL-LABEL: @test6e( 245 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 246 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 247 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16 248 ; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] 249 ; BMI-NOT: select 250 ; GENERIC-NOT: select 251 ; ALL: ret 252 entry: 253 %tobool = icmp eq i32 %x, 0 254 br i1 %tobool, label %cond.end, label %cond.true 255 256 cond.true: ; preds = %entry 257 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 258 %cast = trunc i32 %0 to i16 259 br label %cond.end 260 261 cond.end: ; preds = %entry, %cond.true 262 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 263 ret i16 %cond 264 } 265 266 define i16 @test7e(i64 %x) { 267 ; ALL-LABEL: @test7e( 268 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 269 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 270 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16 271 ; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] 272 ; LZCNT-NOT: select 273 ; GENERIC-NOT: select 274 ; ALL: ret 275 entry: 276 %tobool = icmp eq i64 %x, 0 277 br i1 %tobool, label %cond.end, label %cond.true 278 279 cond.true: ; preds = %entry 280 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 281 %cast = trunc i64 %0 to i16 282 br label %cond.end 283 284 cond.end: ; preds = %entry, %cond.true 285 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 286 ret i16 %cond 287 } 288 289 define i16 @test8e(i32 %x) { 290 ; ALL-LABEL: @test8e( 291 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 292 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 293 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16 294 ; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] 295 ; LZCNT-NOT: select 296 ; GENERIC-NOT: select 297 ; ALL: ret 298 entry: 299 %tobool = icmp eq i32 %x, 0 300 br i1 %tobool, label %cond.end, label %cond.true 301 302 cond.true: ; preds = %entry 303 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 304 %cast = trunc i32 %0 to i16 305 br label %cond.end 306 307 cond.end: ; preds = %entry, %cond.true 308 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 309 ret i16 %cond 310 } 311 312 313 declare i64 @llvm.ctlz.i64(i64, i1) 314 declare i32 @llvm.ctlz.i32(i32, i1) 315 declare i16 @llvm.ctlz.i16(i16, i1) 316 declare i64 @llvm.cttz.i64(i64, i1) 317 declare i32 @llvm.cttz.i32(i32, i1) 318 declare i16 @llvm.cttz.i16(i16, i1) 319