1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2 3; RUN: opt -S -passes=instcombine < %s | FileCheck %s 4 5; When C0 is neither 0 nor 1: 6; umax(nuw_mul(x, C0), x + 1) is optimized to: 7; x == 0 ? 1 : nuw_mul(x, C0) 8; When C0 is not 0: 9; umax(nuw_shl(x, C0), x + 1) is optimized to: 10; x == 0 ? 1 : nuw_shl(x, C0) 11 12; Positive Test Cases for `shl` 13 14define i64 @test_shl_by_2(i64 %x) { 15; CHECK-LABEL: define i64 @test_shl_by_2( 16; CHECK-SAME: i64 [[X:%.*]]) { 17; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 2 18; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 19; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]] 20; CHECK-NEXT: ret i64 [[MAX]] 21; 22 %x1 = add i64 %x, 1 23 %shl = shl nuw i64 %x, 2 24 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 25 ret i64 %max 26} 27 28define i64 @test_shl_by_5(i64 %x) { 29; CHECK-LABEL: define i64 @test_shl_by_5( 30; CHECK-SAME: i64 [[X:%.*]]) { 31; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 5 32; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 33; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]] 34; CHECK-NEXT: ret i64 [[MAX]] 35; 36 %x1 = add i64 %x, 1 37 %shl = shl nuw i64 %x, 5 38 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 39 ret i64 %max 40} 41 42define i64 @test_shl_with_nsw(i64 %x) { 43; CHECK-LABEL: define i64 @test_shl_with_nsw( 44; CHECK-SAME: i64 [[X:%.*]]) { 45; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i64 [[X]], 2 46; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 47; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]] 48; CHECK-NEXT: ret i64 [[MAX]] 49; 50 %x1 = add i64 %x, 1 51 %shl = shl nuw nsw i64 %x, 2 52 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 53 ret i64 %max 54} 55 56define <2 x i64> @test_shl_vector_by_2(<2 x i64> %x) { 57; CHECK-LABEL: define <2 x i64> @test_shl_vector_by_2( 58; CHECK-SAME: <2 x i64> [[X:%.*]]) { 59; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i64> [[X]], splat (i64 2) 60; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> [[X]], zeroinitializer 61; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[TMP1]], <2 x i64> splat (i64 1), <2 x i64> [[SHL]] 62; CHECK-NEXT: ret <2 x i64> [[MAX]] 63; 64 %x1 = add <2 x i64> %x, <i64 1, i64 1> 65 %shl = shl nuw <2 x i64> %x, <i64 2, i64 2> 66 %max = call <2 x i64> @llvm.umax.v2i64(<2 x i64> %shl, <2 x i64> %x1) 67 ret <2 x i64> %max 68} 69 70; Commuted Test Cases for `shl` 71 72define i64 @test_shl_umax_commuted(i64 %x) { 73; CHECK-LABEL: define i64 @test_shl_umax_commuted( 74; CHECK-SAME: i64 [[X:%.*]]) { 75; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2 76; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 77; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]] 78; CHECK-NEXT: ret i64 [[MAX]] 79; 80 %x1 = add i64 %x, 1 81 %shl = shl nuw i64 %x, 2 82 %max = call i64 @llvm.umax.i64(i64 %x1, i64 %shl) 83 ret i64 %max 84} 85 86; Negative Test Cases for `shl` 87 88define i64 @test_shl_by_zero(i64 %x) { 89; CHECK-LABEL: define i64 @test_shl_by_zero( 90; CHECK-SAME: i64 [[X:%.*]]) { 91; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 92; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]]) 93; CHECK-NEXT: ret i64 [[MAX]] 94; 95 %x1 = add i64 %x, 1 96 %shl = shl nuw i64 %x, 0 97 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 98 ret i64 %max 99} 100 101define i64 @test_shl_add_by_2(i64 %x) { 102; CHECK-LABEL: define i64 @test_shl_add_by_2( 103; CHECK-SAME: i64 [[X:%.*]]) { 104; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 2 105; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2 106; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]]) 107; CHECK-NEXT: ret i64 [[MAX]] 108; 109 %x1 = add i64 %x, 2 110 %shl = shl nuw i64 %x, 2 111 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 112 ret i64 %max 113} 114 115define i64 @test_shl_without_nuw(i64 %x) { 116; CHECK-LABEL: define i64 @test_shl_without_nuw( 117; CHECK-SAME: i64 [[X:%.*]]) { 118; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 119; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X]], 2 120; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]]) 121; CHECK-NEXT: ret i64 [[MAX]] 122; 123 %x1 = add i64 %x, 1 124 %shl = shl i64 %x, 2 125 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 126 ret i64 %max 127} 128 129define i64 @test_shl_umin(i64 %x) { 130; CHECK-LABEL: define i64 @test_shl_umin( 131; CHECK-SAME: i64 [[X:%.*]]) { 132; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 133; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2 134; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umin.i64(i64 [[SHL]], i64 [[X1]]) 135; CHECK-NEXT: ret i64 [[MAX]] 136; 137 %x1 = add i64 %x, 1 138 %shl = shl nuw i64 %x, 2 139 %max = call i64 @llvm.umin.i64(i64 %shl, i64 %x1) 140 ret i64 %max 141} 142 143; Multi-use Test Cases for `shl` 144declare void @use(i64) 145 146define i64 @test_shl_multi_use_add(i64 %x) { 147; CHECK-LABEL: define i64 @test_shl_multi_use_add( 148; CHECK-SAME: i64 [[X:%.*]]) { 149; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 150; CHECK-NEXT: call void @use(i64 [[X1]]) 151; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 3 152; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]]) 153; CHECK-NEXT: ret i64 [[MAX]] 154; 155 %x1 = add i64 %x, 1 156 call void @use(i64 %x1) 157 %shl = shl nuw i64 %x, 3 158 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 159 ret i64 %max 160} 161 162define i64 @test_shl_multi_use_shl(i64 %x) { 163; CHECK-LABEL: define i64 @test_shl_multi_use_shl( 164; CHECK-SAME: i64 [[X:%.*]]) { 165; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2 166; CHECK-NEXT: call void @use(i64 [[SHL]]) 167; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 168; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]] 169; CHECK-NEXT: ret i64 [[MAX]] 170; 171 %x1 = add i64 %x, 1 172 %shl = shl nuw i64 %x, 2 173 call void @use(i64 %shl) 174 %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1) 175 ret i64 %max 176} 177 178; Positive Test Cases for `mul` 179 180define i64 @test_mul_by_3(i64 %x) { 181; CHECK-LABEL: define i64 @test_mul_by_3( 182; CHECK-SAME: i64 [[X:%.*]]) { 183; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3 184; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 185; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]] 186; CHECK-NEXT: ret i64 [[MAX]] 187; 188 %x1 = add i64 %x, 1 189 %mul = mul nuw i64 %x, 3 190 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 191 ret i64 %max 192} 193 194define i64 @test_mul_by_5(i64 %x) { 195; CHECK-LABEL: define i64 @test_mul_by_5( 196; CHECK-SAME: i64 [[X:%.*]]) { 197; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 5 198; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 199; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]] 200; CHECK-NEXT: ret i64 [[MAX]] 201; 202 %x1 = add i64 %x, 1 203 %mul = mul nuw i64 %x, 5 204 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 205 ret i64 %max 206} 207 208define i64 @test_mul_with_nsw(i64 %x) { 209; CHECK-LABEL: define i64 @test_mul_with_nsw( 210; CHECK-SAME: i64 [[X:%.*]]) { 211; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[X]], 3 212; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 213; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]] 214; CHECK-NEXT: ret i64 [[MAX]] 215; 216 %x1 = add i64 %x, 1 217 %mul = mul nuw nsw i64 %x, 3 218 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 219 ret i64 %max 220} 221 222define <2 x i64> @test_mul_vector_by_3(<2 x i64> %x) { 223; CHECK-LABEL: define <2 x i64> @test_mul_vector_by_3( 224; CHECK-SAME: <2 x i64> [[X:%.*]]) { 225; CHECK-NEXT: [[MUL:%.*]] = mul nuw <2 x i64> [[X]], splat (i64 3) 226; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> [[X]], zeroinitializer 227; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[TMP1]], <2 x i64> splat (i64 1), <2 x i64> [[MUL]] 228; CHECK-NEXT: ret <2 x i64> [[MAX]] 229; 230 %x1 = add <2 x i64> %x, <i64 1, i64 1> 231 %mul = mul nuw <2 x i64> %x, <i64 3, i64 3> 232 %max = call <2 x i64> @llvm.umax.v2i64(<2 x i64> %mul, <2 x i64> %x1) 233 ret <2 x i64> %max 234} 235 236; Commuted Test Cases for `mul` 237 238define i64 @test_mul_max_commuted(i64 %x) { 239; CHECK-LABEL: define i64 @test_mul_max_commuted( 240; CHECK-SAME: i64 [[X:%.*]]) { 241; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3 242; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 243; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]] 244; CHECK-NEXT: ret i64 [[MAX]] 245; 246 %x1 = add i64 %x, 1 247 %mul = mul nuw i64 %x, 3 248 %max = call i64 @llvm.umax.i64(i64 %x1, i64 %mul) 249 ret i64 %max 250} 251 252; Negative Test Cases for `mul` 253 254define i64 @test_mul_by_zero(i64 %x) { 255; CHECK-LABEL: define i64 @test_mul_by_zero( 256; CHECK-SAME: i64 [[X:%.*]]) { 257; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 258; CHECK-NEXT: ret i64 [[X1]] 259; 260 %x1 = add i64 %x, 1 261 %mul = mul nuw i64 %x, 0 262 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 263 ret i64 %max 264} 265 266define i64 @test_mul_by_1(i64 %x) { 267; CHECK-LABEL: define i64 @test_mul_by_1( 268; CHECK-SAME: i64 [[X:%.*]]) { 269; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 270; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]]) 271; CHECK-NEXT: ret i64 [[MAX]] 272; 273 %x1 = add i64 %x, 1 274 %mul = mul nuw i64 %x, 1 275 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 276 ret i64 %max 277} 278 279define i64 @test_mul_add_by_2(i64 %x) { 280; CHECK-LABEL: define i64 @test_mul_add_by_2( 281; CHECK-SAME: i64 [[X:%.*]]) { 282; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 2 283; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3 284; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]]) 285; CHECK-NEXT: ret i64 [[MAX]] 286; 287 %x1 = add i64 %x, 2 288 %mul = mul nuw i64 %x, 3 289 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 290 ret i64 %max 291} 292 293define i64 @test_mul_without_nuw(i64 %x) { 294; CHECK-LABEL: define i64 @test_mul_without_nuw( 295; CHECK-SAME: i64 [[X:%.*]]) { 296; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 297; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[X]], 3 298; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]]) 299; CHECK-NEXT: ret i64 [[MAX]] 300; 301 %x1 = add i64 %x, 1 302 %mul = mul i64 %x, 3 303 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 304 ret i64 %max 305} 306 307define i64 @test_mul_umin(i64 %x) { 308; CHECK-LABEL: define i64 @test_mul_umin( 309; CHECK-SAME: i64 [[X:%.*]]) { 310; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 311; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3 312; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umin.i64(i64 [[MUL]], i64 [[X1]]) 313; CHECK-NEXT: ret i64 [[MAX]] 314; 315 %x1 = add i64 %x, 1 316 %mul = mul nuw i64 %x, 3 317 %max = call i64 @llvm.umin.i64(i64 %mul, i64 %x1) 318 ret i64 %max 319} 320 321; Multi-use Test Cases for `mul` 322 323define i64 @test_mul_multi_use_add(i64 %x) { 324; CHECK-LABEL: define i64 @test_mul_multi_use_add( 325; CHECK-SAME: i64 [[X:%.*]]) { 326; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1 327; CHECK-NEXT: call void @use(i64 [[X1]]) 328; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[X]], 3 329; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]]) 330; CHECK-NEXT: ret i64 [[MAX]] 331; 332 %x1 = add i64 %x, 1 333 call void @use(i64 %x1) 334 %mul = mul nuw i64 %x, 3 335 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 336 ret i64 %max 337} 338 339define i64 @test_mul_multi_use_mul(i64 %x) { 340; CHECK-LABEL: define i64 @test_mul_multi_use_mul( 341; CHECK-SAME: i64 [[X:%.*]]) { 342; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3 343; CHECK-NEXT: call void @use(i64 [[MUL]]) 344; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0 345; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]] 346; CHECK-NEXT: ret i64 [[MAX]] 347; 348 %x1 = add i64 %x, 1 349 %mul = mul nuw i64 %x, 3 350 call void @use(i64 %mul) 351 %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1) 352 ret i64 %max 353} 354