1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i32) 5 6define i64 @match_unsigned(i64 %x) { 7; CHECK-LABEL: @match_unsigned( 8; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[X:%.*]], 19136 9; CHECK-NEXT: ret i64 [[UREM]] 10; 11 %t = urem i64 %x, 299 12 %t1 = udiv i64 %x, 299 13 %t2 = urem i64 %t1, 64 14 %t3 = mul i64 %t2, 299 15 %t4 = add i64 %t, %t3 16 ret i64 %t4 17} 18 19define <2 x i64> @match_unsigned_vector(<2 x i64> %x) { 20; CHECK-LABEL: @match_unsigned_vector( 21; CHECK-NEXT: bb: 22; CHECK-NEXT: [[UREM:%.*]] = urem <2 x i64> [[X:%.*]], splat (i64 19136) 23; CHECK-NEXT: ret <2 x i64> [[UREM]] 24; 25bb: 26 %tmp = urem <2 x i64> %x, <i64 299, i64 299> 27 %tmp1 = udiv <2 x i64> %x, <i64 299, i64 299> 28 %tmp2 = urem <2 x i64> %tmp1, <i64 64, i64 64> 29 %tmp3 = mul <2 x i64> %tmp2, <i64 299, i64 299> 30 %tmp4 = add <2 x i64> %tmp, %tmp3 31 ret <2 x i64> %tmp4 32} 33define i64 @match_andAsRem_lshrAsDiv_shlAsMul(i64 %x) { 34; CHECK-LABEL: @match_andAsRem_lshrAsDiv_shlAsMul( 35; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[X:%.*]], 576 36; CHECK-NEXT: ret i64 [[UREM]] 37; 38 %t = and i64 %x, 63 39 %t1 = lshr i64 %x, 6 40 %t2 = urem i64 %t1, 9 41 %t3 = shl i64 %t2, 6 42 %t4 = add i64 %t, %t3 43 ret i64 %t4 44} 45 46define i64 @match_signed(i64 %x) { 47; CHECK-LABEL: @match_signed( 48; CHECK-NEXT: [[SREM1:%.*]] = srem i64 [[X:%.*]], 172224 49; CHECK-NEXT: ret i64 [[SREM1]] 50; 51 %t = srem i64 %x, 299 52 %t1 = sdiv i64 %x, 299 53 %t2 = srem i64 %t1, 64 54 %t3 = sdiv i64 %x, 19136 55 %t4 = srem i64 %t3, 9 56 %t5 = mul i64 %t2, 299 57 %t6 = add i64 %t, %t5 58 %t7 = mul i64 %t4, 19136 59 %t8 = add i64 %t6, %t7 60 ret i64 %t8 61} 62 63define <2 x i64> @match_signed_vector(<2 x i64> %x) { 64; CHECK-LABEL: @match_signed_vector( 65; CHECK-NEXT: bb: 66; CHECK-NEXT: [[SREM1:%.*]] = srem <2 x i64> [[X:%.*]], splat (i64 172224) 67; CHECK-NEXT: ret <2 x i64> [[SREM1]] 68; 69bb: 70 %tmp = srem <2 x i64> %x, <i64 299, i64 299> 71 %tmp1 = sdiv <2 x i64> %x, <i64 299, i64 299> 72 %tmp2 = srem <2 x i64> %tmp1, <i64 64, i64 64> 73 %tmp3 = sdiv <2 x i64> %x, <i64 19136, i64 19136> 74 %tmp4 = srem <2 x i64> %tmp3, <i64 9, i64 9> 75 %tmp5 = mul <2 x i64> %tmp2, <i64 299, i64 299> 76 %tmp6 = add <2 x i64> %tmp, %tmp5 77 %tmp7 = mul <2 x i64> %tmp4, <i64 19136, i64 19136> 78 %tmp8 = add <2 x i64> %tmp6, %tmp7 79 ret <2 x i64> %tmp8 80} 81 82define i64 @not_match_inconsistent_signs(i64 %x) { 83; CHECK-LABEL: @not_match_inconsistent_signs( 84; CHECK-NEXT: [[T:%.*]] = urem i64 [[X:%.*]], 299 85; CHECK-NEXT: [[T1:%.*]] = sdiv i64 [[X]], 299 86; CHECK-NEXT: [[T2:%.*]] = and i64 [[T1]], 63 87; CHECK-NEXT: [[T3:%.*]] = mul nuw nsw i64 [[T2]], 299 88; CHECK-NEXT: [[T4:%.*]] = add nuw nsw i64 [[T]], [[T3]] 89; CHECK-NEXT: ret i64 [[T4]] 90; 91 %t = urem i64 %x, 299 92 %t1 = sdiv i64 %x, 299 93 %t2 = urem i64 %t1, 64 94 %t3 = mul i64 %t2, 299 95 %t4 = add i64 %t, %t3 96 ret i64 %t4 97} 98 99define i64 @not_match_inconsistent_values(i64 %x) { 100; CHECK-LABEL: @not_match_inconsistent_values( 101; CHECK-NEXT: [[T:%.*]] = urem i64 [[X:%.*]], 299 102; CHECK-NEXT: [[T1:%.*]] = udiv i64 [[X]], 29 103; CHECK-NEXT: [[T2:%.*]] = and i64 [[T1]], 63 104; CHECK-NEXT: [[T3:%.*]] = mul nuw nsw i64 [[T2]], 299 105; CHECK-NEXT: [[T4:%.*]] = add nuw nsw i64 [[T]], [[T3]] 106; CHECK-NEXT: ret i64 [[T4]] 107; 108 %t = urem i64 %x, 299 109 %t1 = udiv i64 %x, 29 110 %t2 = urem i64 %t1, 64 111 %t3 = mul i64 %t2, 299 112 %t4 = add i64 %t, %t3 113 ret i64 %t4 114} 115 116define i32 @not_match_overflow(i32 %x) { 117; CHECK-LABEL: @not_match_overflow( 118; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 119; CHECK-NEXT: [[T:%.*]] = urem i32 [[X_FR]], 299 120; CHECK-NEXT: [[TMP1:%.*]] = urem i32 [[X_FR]], 299 121; CHECK-NEXT: [[T3:%.*]] = sub nuw i32 [[X_FR]], [[TMP1]] 122; CHECK-NEXT: [[T4:%.*]] = add i32 [[T]], [[T3]] 123; CHECK-NEXT: ret i32 [[T4]] 124; 125 %t = urem i32 %x, 299 126 %t1 = udiv i32 %x, 299 127 %t2 = urem i32 %t1, 147483647 128 %t3 = mul i32 %t2, 299 129 %t4 = add i32 %t, %t3 130 ret i32 %t4 131} 132 133; Tests from PR76128. 134define i32 @fold_add_udiv_urem(i32 noundef %val) { 135; CHECK-LABEL: @fold_add_udiv_urem( 136; CHECK-NEXT: entry: 137; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 138; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6 139; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]] 140; CHECK-NEXT: ret i32 [[ADD]] 141; 142entry: 143 %div = udiv i32 %val, 10 144 %shl = shl i32 %div, 4 145 %rem = urem i32 %val, 10 146 %add = add i32 %shl, %rem 147 ret i32 %add 148} 149define i32 @fold_add_sdiv_srem(i32 noundef %val) { 150; CHECK-LABEL: @fold_add_sdiv_srem( 151; CHECK-NEXT: entry: 152; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[VAL:%.*]], 10 153; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i32 [[DIV]], 6 154; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]] 155; CHECK-NEXT: ret i32 [[ADD]] 156; 157entry: 158 %div = sdiv i32 %val, 10 159 %shl = shl i32 %div, 4 160 %rem = srem i32 %val, 10 161 %add = add i32 %shl, %rem 162 ret i32 %add 163} 164define i32 @fold_add_udiv_urem_to_mul(i32 noundef %val) { 165; CHECK-LABEL: @fold_add_udiv_urem_to_mul( 166; CHECK-NEXT: entry: 167; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL:%.*]], 3 168; CHECK-NEXT: ret i32 [[ADD]] 169; 170entry: 171 %div = udiv i32 %val, 7 172 %mul1 = mul i32 %div, 21 173 %rem = urem i32 %val, 7 174 %mul2 = mul i32 %rem, 3 175 %add = add i32 %mul1, %mul2 176 ret i32 %add 177} 178define i32 @fold_add_udiv_urem_to_mul_multiuse(i32 noundef %val) { 179; CHECK-LABEL: @fold_add_udiv_urem_to_mul_multiuse( 180; CHECK-NEXT: entry: 181; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL:%.*]], 7 182; CHECK-NEXT: call void @use(i32 [[REM]]) 183; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL]], 3 184; CHECK-NEXT: ret i32 [[ADD]] 185; 186entry: 187 %div = udiv i32 %val, 7 188 %mul1 = mul i32 %div, 21 189 %rem = urem i32 %val, 7 190 call void @use(i32 %rem) 191 %mul2 = mul i32 %rem, 3 192 %add = add i32 %mul1, %mul2 193 ret i32 %add 194} 195define i32 @fold_add_udiv_urem_commuted(i32 noundef %val) { 196; CHECK-LABEL: @fold_add_udiv_urem_commuted( 197; CHECK-NEXT: entry: 198; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 199; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6 200; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]] 201; CHECK-NEXT: ret i32 [[ADD]] 202; 203entry: 204 %div = udiv i32 %val, 10 205 %shl = shl i32 %div, 4 206 %rem = urem i32 %val, 10 207 %add = add i32 %rem, %shl 208 ret i32 %add 209} 210define i32 @fold_add_udiv_urem_or_disjoint(i32 noundef %val) { 211; CHECK-LABEL: @fold_add_udiv_urem_or_disjoint( 212; CHECK-NEXT: entry: 213; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 214; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6 215; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]] 216; CHECK-NEXT: ret i32 [[ADD]] 217; 218entry: 219 %div = udiv i32 %val, 10 220 %shl = shl i32 %div, 4 221 %rem = urem i32 %val, 10 222 %add = or disjoint i32 %shl, %rem 223 ret i32 %add 224} 225; Negative tests 226define i32 @fold_add_udiv_urem_without_noundef(i32 %val) { 227; CHECK-LABEL: @fold_add_udiv_urem_without_noundef( 228; CHECK-NEXT: entry: 229; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 230; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4 231; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10 232; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]] 233; CHECK-NEXT: ret i32 [[ADD]] 234; 235entry: 236 %div = udiv i32 %val, 10 237 %shl = shl i32 %div, 4 238 %rem = urem i32 %val, 10 239 %add = add i32 %shl, %rem 240 ret i32 %add 241} 242define i32 @fold_add_udiv_urem_multiuse_mul(i32 noundef %val) { 243; CHECK-LABEL: @fold_add_udiv_urem_multiuse_mul( 244; CHECK-NEXT: entry: 245; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 246; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4 247; CHECK-NEXT: call void @use(i32 [[SHL]]) 248; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10 249; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]] 250; CHECK-NEXT: ret i32 [[ADD]] 251; 252entry: 253 %div = udiv i32 %val, 10 254 %shl = shl i32 %div, 4 255 call void @use(i32 %shl) 256 %rem = urem i32 %val, 10 257 %add = add i32 %shl, %rem 258 ret i32 %add 259} 260define i32 @fold_add_udiv_srem(i32 noundef %val) { 261; CHECK-LABEL: @fold_add_udiv_srem( 262; CHECK-NEXT: entry: 263; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10 264; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4 265; CHECK-NEXT: [[REM:%.*]] = srem i32 [[VAL]], 10 266; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[REM]] 267; CHECK-NEXT: ret i32 [[ADD]] 268; 269entry: 270 %div = udiv i32 %val, 10 271 %shl = shl i32 %div, 4 272 %rem = srem i32 %val, 10 273 %add = add i32 %shl, %rem 274 ret i32 %add 275} 276define i32 @fold_add_udiv_urem_non_constant(i32 noundef %val, i32 noundef %c) { 277; CHECK-LABEL: @fold_add_udiv_urem_non_constant( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], [[C:%.*]] 280; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4 281; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], [[C]] 282; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[REM]] 283; CHECK-NEXT: ret i32 [[ADD]] 284; 285entry: 286 %div = udiv i32 %val, %c 287 %shl = shl i32 %div, 4 288 %rem = urem i32 %val, %c 289 %add = add i32 %shl, %rem 290 ret i32 %add 291} 292