1 ; RUN: opt -instcombine -S < %s | FileCheck %s 2 3 ; This test is to verify that the instruction combiner is able to fold 4 ; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with 5 ; the 'is_zero_undef' flag cleared. 6 7 define i16 @test1(i16 %x) { 8 ; CHECK-LABEL: @test1( 9 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false) 10 ; CHECK-NEXT: ret i16 [[VAR]] 11 entry: 12 %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 13 %tobool = icmp ne i16 %x, 0 14 %cond = select i1 %tobool, i16 %0, i16 16 15 ret i16 %cond 16 } 17 18 define i32 @test2(i32 %x) { 19 ; CHECK-LABEL: @test2( 20 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 21 ; CHECK-NEXT: ret i32 [[VAR]] 22 entry: 23 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 24 %tobool = icmp ne i32 %x, 0 25 %cond = select i1 %tobool, i32 %0, i32 32 26 ret i32 %cond 27 } 28 29 define i64 @test3(i64 %x) { 30 ; CHECK-LABEL: @test3( 31 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false) 32 ; CHECK-NEXT: ret i64 [[VAR]] 33 entry: 34 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 35 %tobool = icmp ne i64 %x, 0 36 %cond = select i1 %tobool, i64 %0, i64 64 37 ret i64 %cond 38 } 39 40 define i16 @test4(i16 %x) { 41 ; CHECK-LABEL: @test4( 42 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false) 43 ; CHECK-NEXT: ret i16 [[VAR]] 44 entry: 45 %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 46 %tobool = icmp eq i16 %x, 0 47 %cond = select i1 %tobool, i16 16, i16 %0 48 ret i16 %cond 49 } 50 51 define i32 @test5(i32 %x) { 52 ; CHECK-LABEL: @test5( 53 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 54 ; CHECK-NEXT: ret i32 [[VAR]] 55 entry: 56 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 57 %tobool = icmp eq i32 %x, 0 58 %cond = select i1 %tobool, i32 32, i32 %0 59 ret i32 %cond 60 } 61 62 define i64 @test6(i64 %x) { 63 ; CHECK-LABEL: @test6( 64 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false) 65 ; CHECK-NEXT: ret i64 [[VAR]] 66 entry: 67 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 68 %tobool = icmp eq i64 %x, 0 69 %cond = select i1 %tobool, i64 64, i64 %0 70 ret i64 %cond 71 } 72 73 define i16 @test1b(i16 %x) { 74 ; CHECK-LABEL: @test1b( 75 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false) 76 ; CHECK-NEXT: ret i16 [[VAR]] 77 entry: 78 %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 79 %tobool = icmp ne i16 %x, 0 80 %cond = select i1 %tobool, i16 %0, i16 16 81 ret i16 %cond 82 } 83 84 define i32 @test2b(i32 %x) { 85 ; CHECK-LABEL: @test2b( 86 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 87 ; CHECK-NEXT: ret i32 [[VAR]] 88 entry: 89 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 90 %tobool = icmp ne i32 %x, 0 91 %cond = select i1 %tobool, i32 %0, i32 32 92 ret i32 %cond 93 } 94 95 define i64 @test3b(i64 %x) { 96 ; CHECK-LABEL: @test3b( 97 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false) 98 ; CHECK-NEXT: ret i64 [[VAR]] 99 entry: 100 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 101 %tobool = icmp ne i64 %x, 0 102 %cond = select i1 %tobool, i64 %0, i64 64 103 ret i64 %cond 104 } 105 106 define i16 @test4b(i16 %x) { 107 ; CHECK-LABEL: @test4b( 108 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false) 109 ; CHECK-NEXT: ret i16 [[VAR]] 110 entry: 111 %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 112 %tobool = icmp eq i16 %x, 0 113 %cond = select i1 %tobool, i16 16, i16 %0 114 ret i16 %cond 115 } 116 117 define i32 @test5b(i32 %x) { 118 ; CHECK-LABEL: @test5b( 119 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 120 ; CHECK-NEXT: ret i32 [[VAR]] 121 entry: 122 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 123 %tobool = icmp eq i32 %x, 0 124 %cond = select i1 %tobool, i32 32, i32 %0 125 ret i32 %cond 126 } 127 128 define i64 @test6b(i64 %x) { 129 ; CHECK-LABEL: @test6b( 130 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false) 131 ; CHECK-NEXT: ret i64 [[VAR]] 132 entry: 133 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 134 %tobool = icmp eq i64 %x, 0 135 %cond = select i1 %tobool, i64 64, i64 %0 136 ret i64 %cond 137 } 138 139 define i32 @test1c(i16 %x) { 140 ; CHECK-LABEL: @test1c( 141 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false) 142 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32 143 ; CHECK-NEXT: ret i32 [[VAR2]] 144 entry: 145 %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 146 %cast2 = zext i16 %0 to i32 147 %tobool = icmp ne i16 %x, 0 148 %cond = select i1 %tobool, i32 %cast2, i32 16 149 ret i32 %cond 150 } 151 152 define i64 @test2c(i16 %x) { 153 ; CHECK-LABEL: @test2c( 154 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false) 155 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64 156 ; CHECK-NEXT: ret i64 [[VAR2]] 157 entry: 158 %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 159 %conv = zext i16 %0 to i64 160 %tobool = icmp ne i16 %x, 0 161 %cond = select i1 %tobool, i64 %conv, i64 16 162 ret i64 %cond 163 } 164 165 define i64 @test3c(i32 %x) { 166 ; CHECK-LABEL: @test3c( 167 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 168 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64 169 ; CHECK-NEXT: ret i64 [[VAR2]] 170 entry: 171 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 172 %conv = zext i32 %0 to i64 173 %tobool = icmp ne i32 %x, 0 174 %cond = select i1 %tobool, i64 %conv, i64 32 175 ret i64 %cond 176 } 177 178 define i32 @test4c(i16 %x) { 179 ; CHECK-LABEL: @test4c( 180 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false) 181 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32 182 ; CHECK-NEXT: ret i32 [[VAR2]] 183 entry: 184 %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 185 %cast = zext i16 %0 to i32 186 %tobool = icmp ne i16 %x, 0 187 %cond = select i1 %tobool, i32 %cast, i32 16 188 ret i32 %cond 189 } 190 191 define i64 @test5c(i16 %x) { 192 ; CHECK-LABEL: @test5c( 193 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false) 194 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64 195 ; CHECK-NEXT: ret i64 [[VAR2]] 196 entry: 197 %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 198 %cast = zext i16 %0 to i64 199 %tobool = icmp ne i16 %x, 0 200 %cond = select i1 %tobool, i64 %cast, i64 16 201 ret i64 %cond 202 } 203 204 define i64 @test6c(i32 %x) { 205 ; CHECK-LABEL: @test6c( 206 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 207 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64 208 ; CHECK-NEXT: ret i64 [[VAR2]] 209 entry: 210 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 211 %cast = zext i32 %0 to i64 212 %tobool = icmp ne i32 %x, 0 213 %cond = select i1 %tobool, i64 %cast, i64 32 214 ret i64 %cond 215 } 216 217 define i16 @test1d(i64 %x) { 218 ; CHECK-LABEL: @test1d( 219 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false) 220 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16 221 ; CHECK-NEXT: ret i16 [[VAR2]] 222 entry: 223 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 224 %conv = trunc i64 %0 to i16 225 %tobool = icmp ne i64 %x, 0 226 %cond = select i1 %tobool, i16 %conv, i16 64 227 ret i16 %cond 228 } 229 230 define i32 @test2d(i64 %x) { 231 ; CHECK-LABEL: @test2d( 232 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false) 233 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32 234 ; CHECK-NEXT: ret i32 [[VAR2]] 235 entry: 236 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 237 %cast = trunc i64 %0 to i32 238 %tobool = icmp ne i64 %x, 0 239 %cond = select i1 %tobool, i32 %cast, i32 64 240 ret i32 %cond 241 } 242 243 define i16 @test3d(i32 %x) { 244 ; CHECK-LABEL: @test3d( 245 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 246 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16 247 ; CHECK-NEXT: ret i16 [[VAR2]] 248 entry: 249 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 250 %cast = trunc i32 %0 to i16 251 %tobool = icmp ne i32 %x, 0 252 %cond = select i1 %tobool, i16 %cast, i16 32 253 ret i16 %cond 254 } 255 256 define i16 @test4d(i64 %x) { 257 ; CHECK-LABEL: @test4d( 258 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false) 259 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16 260 ; CHECK-NEXT: ret i16 [[VAR2]] 261 entry: 262 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 263 %cast = trunc i64 %0 to i16 264 %tobool = icmp ne i64 %x, 0 265 %cond = select i1 %tobool, i16 %cast, i16 64 266 ret i16 %cond 267 } 268 269 define i32 @test5d(i64 %x) { 270 ; CHECK-LABEL: @test5d( 271 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false) 272 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32 273 ; CHECK-NEXT: ret i32 [[VAR2]] 274 entry: 275 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 276 %cast = trunc i64 %0 to i32 277 %tobool = icmp ne i64 %x, 0 278 %cond = select i1 %tobool, i32 %cast, i32 64 279 ret i32 %cond 280 } 281 282 define i16 @test6d(i32 %x) { 283 ; CHECK-LABEL: @test6d( 284 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 285 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16 286 ; CHECK-NEXT: ret i16 [[VAR2]] 287 entry: 288 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 289 %cast = trunc i32 %0 to i16 290 %tobool = icmp ne i32 %x, 0 291 %cond = select i1 %tobool, i16 %cast, i16 32 292 ret i16 %cond 293 } 294 295 define i64 @select_bug1(i32 %x) { 296 ; CHECK-LABEL: @select_bug1( 297 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 298 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64 299 ; CHECK-NEXT: ret i64 [[VAR2]] 300 entry: 301 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 302 %conv = zext i32 %0 to i64 303 %tobool = icmp ne i32 %x, 0 304 %cond = select i1 %tobool, i64 %conv, i64 32 305 ret i64 %cond 306 } 307 308 define i16 @select_bug2(i32 %x) { 309 ; CHECK-LABEL: @select_bug2( 310 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 311 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16 312 ; CHECK-NEXT: ret i16 [[VAR2]] 313 entry: 314 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 315 %conv = trunc i32 %0 to i16 316 %tobool = icmp ne i32 %x, 0 317 %cond = select i1 %tobool, i16 %conv, i16 32 318 ret i16 %cond 319 } 320 321 322 declare i16 @llvm.ctlz.i16(i16, i1) 323 declare i32 @llvm.ctlz.i32(i32, i1) 324 declare i64 @llvm.ctlz.i64(i64, i1) 325 declare i16 @llvm.cttz.i16(i16, i1) 326 declare i32 @llvm.cttz.i32(i32, i1) 327 declare i64 @llvm.cttz.i64(i64, i1) 328