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 7define 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]] 11entry: 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 18define 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]] 22entry: 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 29define 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]] 33entry: 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 40define 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]] 44entry: 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 51define 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]] 55entry: 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 62define 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]] 66entry: 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 73define 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]] 77entry: 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 84define 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]] 88entry: 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 95define 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]] 99entry: 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 106define 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]] 110entry: 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 117define 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]] 121entry: 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 128define 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]] 132entry: 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 139define 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]] 144entry: 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 152define 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]] 157entry: 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 165define 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]] 170entry: 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 178define 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]] 183entry: 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 191define 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]] 196entry: 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 204define 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]] 209entry: 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 217define 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]] 222entry: 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 230define 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]] 235entry: 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 243define 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]] 248entry: 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 256define 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]] 261entry: 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 269define 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]] 274entry: 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 282define 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]] 287entry: 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 295define 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]] 300entry: 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 308define 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]] 313entry: 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 321define i128 @test7(i128 %x) { 322; CHECK-LABEL: @test7( 323; CHECK-NEXT: [[TMP1:%.*]] = tail call i128 @llvm.ctlz.i128(i128 [[X:%.*]], i1 false), !range !3 324; CHECK-NEXT: ret i128 [[TMP1]] 325; 326 %1 = tail call i128 @llvm.ctlz.i128(i128 %x, i1 true) 327 %tobool = icmp ne i128 %x, 0 328 %cond = select i1 %tobool, i128 %1, i128 128 329 ret i128 %cond 330} 331 332define i128 @test8(i128 %x) { 333; CHECK-LABEL: @test8( 334; CHECK-NEXT: [[TMP1:%.*]] = tail call i128 @llvm.cttz.i128(i128 [[X:%.*]], i1 false), !range !3 335; CHECK-NEXT: ret i128 [[TMP1]] 336; 337 %1 = tail call i128 @llvm.cttz.i128(i128 %x, i1 true) 338 %tobool = icmp ne i128 %x, 0 339 %cond = select i1 %tobool, i128 %1, i128 128 340 ret i128 %cond 341} 342 343declare i16 @llvm.ctlz.i16(i16, i1) 344declare i32 @llvm.ctlz.i32(i32, i1) 345declare i64 @llvm.ctlz.i64(i64, i1) 346declare i128 @llvm.ctlz.i128(i128, i1) 347declare i16 @llvm.cttz.i16(i16, i1) 348declare i32 @llvm.cttz.i32(i32, i1) 349declare i64 @llvm.cttz.i64(i64, i1) 350declare i128 @llvm.cttz.i128(i128, i1) 351