1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4define i32 @cttz_abs(i32 %x) { 5; CHECK-LABEL: @cttz_abs( 6; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true), [[RNG0:!range !.*]] 7; CHECK-NEXT: ret i32 [[R]] 8; 9 %c = icmp slt i32 %x, 0 10 %s = sub i32 0, %x 11 %d = select i1 %c, i32 %s, i32 %x 12 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 13 ret i32 %r 14} 15 16define <2 x i64> @cttz_abs_vec(<2 x i64> %x) { 17; CHECK-LABEL: @cttz_abs_vec( 18; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false) 19; CHECK-NEXT: ret <2 x i64> [[R]] 20; 21 %c = icmp slt <2 x i64> %x, zeroinitializer 22 %s = sub <2 x i64> zeroinitializer, %x 23 %d = select <2 x i1> %c, <2 x i64> %s, <2 x i64> %x 24 %r = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %d) 25 ret <2 x i64> %r 26} 27 28define i32 @cttz_abs2(i32 %x) { 29; CHECK-LABEL: @cttz_abs2( 30; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], 0 31; CHECK-NEXT: call void @use_cond(i1 [[C]]) 32; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), [[RNG0]] 33; CHECK-NEXT: ret i32 [[R]] 34; 35 %c = icmp sgt i32 %x, 0 36 call void @use_cond(i1 %c) 37 %s = sub i32 0, %x 38 %d = select i1 %c, i32 %x, i32 %s 39 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 40 ret i32 %r 41} 42 43define i32 @cttz_abs3(i32 %x) { 44; CHECK-LABEL: @cttz_abs3( 45; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], -1 46; CHECK-NEXT: call void @use_cond(i1 [[C]]) 47; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), [[RNG0]] 48; CHECK-NEXT: ret i32 [[R]] 49; 50 %c = icmp sgt i32 %x, -1 51 call void @use_cond(i1 %c) 52 %s = sub i32 0, %x 53 %d = select i1 %c, i32 %x, i32 %s 54 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 55 ret i32 %r 56} 57 58define i32 @cttz_abs4(i32 %x) { 59; CHECK-LABEL: @cttz_abs4( 60; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true), [[RNG0]] 61; CHECK-NEXT: ret i32 [[R]] 62; 63 %c = icmp slt i32 %x, 1 64 %s = sub i32 0, %x 65 %d = select i1 %c, i32 %s, i32 %x 66 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 67 ret i32 %r 68} 69 70define i32 @cttz_nabs(i32 %x) { 71; CHECK-LABEL: @cttz_nabs( 72; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false), [[RNG0]] 73; CHECK-NEXT: ret i32 [[R]] 74; 75 %c = icmp slt i32 %x, 0 76 %s = sub i32 0, %x 77 %d = select i1 %c, i32 %x, i32 %s 78 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 false) 79 ret i32 %r 80} 81 82define <2 x i64> @cttz_nabs_vec(<2 x i64> %x) { 83; CHECK-LABEL: @cttz_nabs_vec( 84; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false) 85; CHECK-NEXT: ret <2 x i64> [[R]] 86; 87 %c = icmp slt <2 x i64> %x, zeroinitializer 88 %s = sub <2 x i64> zeroinitializer, %x 89 %d = select <2 x i1> %c, <2 x i64> %x, <2 x i64> %s 90 %r = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %d) 91 ret <2 x i64> %r 92} 93 94define i64 @cttz_abs_64(i64 %x) { 95; CHECK-LABEL: @cttz_abs_64( 96; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false), [[RNG1:!range !.*]] 97; CHECK-NEXT: ret i64 [[R]] 98; 99 %c = icmp slt i64 %x, 0 100 %s = sub i64 0, %x 101 %d = select i1 %c, i64 %s, i64 %x 102 %r = tail call i64 @llvm.cttz.i64(i64 %d) 103 ret i64 %r 104} 105 106define i32 @cttz_abs_multiuse(i32 %x) { 107; CHECK-LABEL: @cttz_abs_multiuse( 108; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0 109; CHECK-NEXT: [[S:%.*]] = sub i32 0, [[X]] 110; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[S]], i32 [[X]] 111; CHECK-NEXT: call void @use_abs(i32 [[D]]) 112; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), [[RNG0]] 113; CHECK-NEXT: ret i32 [[R]] 114; 115 %c = icmp slt i32 %x, 1 116 %s = sub i32 0, %x 117 %d = select i1 %c, i32 %s, i32 %x 118 call void @use_abs(i32 %d) 119 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 120 ret i32 %r 121} 122 123define i32 @cttz_nabs_multiuse(i32 %x) { 124; CHECK-LABEL: @cttz_nabs_multiuse( 125; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0 126; CHECK-NEXT: [[S:%.*]] = sub i32 0, [[X]] 127; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[S]] 128; CHECK-NEXT: call void @use_abs(i32 [[D]]) 129; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true), [[RNG0]] 130; CHECK-NEXT: ret i32 [[R]] 131; 132 %c = icmp slt i32 %x, 1 133 %s = sub i32 0, %x 134 %d = select i1 %c, i32 %x, i32 %s 135 call void @use_abs(i32 %d) 136 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 137 ret i32 %r 138} 139 140; Negative tests 141 142define i32 @no_cttz_abs(i32 %x) { 143; CHECK-LABEL: @no_cttz_abs( 144; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 2 145; CHECK-NEXT: [[S:%.*]] = sub i32 0, [[X]] 146; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[S]], i32 [[X]] 147; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), [[RNG0]] 148; CHECK-NEXT: ret i32 [[R]] 149; 150 %c = icmp slt i32 %x, 2 151 %s = sub i32 0, %x 152 %d = select i1 %c, i32 %s, i32 %x 153 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 154 ret i32 %r 155} 156 157define i32 @no_cttz_abs2(i32 %x) { 158; CHECK-LABEL: @no_cttz_abs2( 159; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0 160; CHECK-NEXT: [[S:%.*]] = sub i32 1, [[X]] 161; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[S]], i32 [[X]] 162; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), [[RNG0]] 163; CHECK-NEXT: ret i32 [[R]] 164; 165 %c = icmp slt i32 %x, 0 166 %s = sub i32 1, %x 167 %d = select i1 %c, i32 %s, i32 %x 168 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 169 ret i32 %r 170} 171 172define i32 @no_cttz_abs3(i32 %x) { 173; CHECK-LABEL: @no_cttz_abs3( 174; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], -2 175; CHECK-NEXT: call void @use_cond(i1 [[C]]) 176; CHECK-NEXT: [[S:%.*]] = sub i32 0, [[X]] 177; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[S]] 178; CHECK-NEXT: [[R:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[D]], i1 true), [[RNG0]] 179; CHECK-NEXT: ret i32 [[R]] 180; 181 %c = icmp sgt i32 %x, -2 182 call void @use_cond(i1 %c) 183 %s = sub i32 0, %x 184 %d = select i1 %c, i32 %x, i32 %s 185 %r = tail call i32 @llvm.cttz.i32(i32 %d, i1 true) 186 ret i32 %r 187} 188 189define <2 x i64> @no_cttz_abs_vec(<2 x i64> %x) { 190; CHECK-LABEL: @no_cttz_abs_vec( 191; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i64> [[X:%.*]], <i64 2, i64 1> 192; CHECK-NEXT: [[S:%.*]] = sub <2 x i64> <i64 1, i64 0>, [[X]] 193; CHECK-NEXT: [[D:%.*]] = select <2 x i1> [[C]], <2 x i64> [[S]], <2 x i64> [[X]] 194; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[D]], i1 false) 195; CHECK-NEXT: ret <2 x i64> [[R]] 196; 197 %c = icmp slt <2 x i64> %x, <i64 2, i64 1> 198 %s = sub <2 x i64> <i64 1, i64 0>, %x 199 %d = select <2 x i1> %c, <2 x i64> %s, <2 x i64> %x 200 %r = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %d) 201 ret <2 x i64> %r 202} 203 204define <2 x i64> @no_cttz_nabs_vec(<2 x i64> %x) { 205; CHECK-LABEL: @no_cttz_nabs_vec( 206; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i64> [[X:%.*]], <i64 2, i64 1> 207; CHECK-NEXT: [[S:%.*]] = sub <2 x i64> <i64 1, i64 0>, [[X]] 208; CHECK-NEXT: [[D:%.*]] = select <2 x i1> [[C]], <2 x i64> [[X]], <2 x i64> [[S]] 209; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[D]], i1 false) 210; CHECK-NEXT: ret <2 x i64> [[R]] 211; 212 %c = icmp slt <2 x i64> %x, <i64 2, i64 1> 213 %s = sub <2 x i64> <i64 1, i64 0>, %x 214 %d = select <2 x i1> %c, <2 x i64> %x, <2 x i64> %s 215 %r = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %d) 216 ret <2 x i64> %r 217} 218 219define i32 @cttz_abs_intrin(i32 %x) { 220; CHECK-LABEL: @cttz_abs_intrin( 221; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false), [[RNG0]] 222; CHECK-NEXT: ret i32 [[R]] 223; 224 %a = call i32 @llvm.abs.i32(i32 %x, i1 false) 225 %r = call i32 @llvm.cttz.i32(i32 %a, i1 false) 226 ret i32 %r 227} 228 229define i32 @cttz_nabs_intrin(i32 %x) { 230; CHECK-LABEL: @cttz_nabs_intrin( 231; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false), [[RNG0]] 232; CHECK-NEXT: ret i32 [[R]] 233; 234 %a = call i32 @llvm.abs.i32(i32 %x, i1 false) 235 %n = sub i32 0, %a 236 %r = call i32 @llvm.cttz.i32(i32 %n, i1 false) 237 ret i32 %r 238} 239 240declare void @use_cond(i1) 241declare void @use_abs(i32) 242declare i32 @llvm.cttz.i32(i32, i1) 243declare i64 @llvm.cttz.i64(i64) 244declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>) 245declare i32 @llvm.abs.i32(i32, i1) 246