1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; https://bugs.llvm.org/show_bug.cgi?id=37603 5; https://reviews.llvm.org/D46760#1123713 6 7; Pattern: 8; x >> y << y 9; Should be transformed into: 10; x & (-1 << y) 11 12; ============================================================================ ; 13; Basic positive tests 14; ============================================================================ ; 15 16define i32 @positive_samevar(i32 %x, i32 %y) { 17; CHECK-LABEL: @positive_samevar( 18; CHECK-NEXT: [[TMP1:%.*]] = shl i32 -1, [[Y:%.*]] 19; CHECK-NEXT: [[RET:%.*]] = and i32 [[TMP1]], [[X:%.*]] 20; CHECK-NEXT: ret i32 [[RET]] 21; 22 %tmp0 = ashr i32 %x, %y 23 %ret = shl i32 %tmp0, %y 24 ret i32 %ret 25} 26 27define i32 @positive_sameconst(i32 %x) { 28; CHECK-LABEL: @positive_sameconst( 29; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -32 30; CHECK-NEXT: ret i32 [[TMP1]] 31; 32 %tmp0 = ashr i32 %x, 5 33 %ret = shl i32 %tmp0, 5 34 ret i32 %ret 35} 36 37define i32 @positive_biggerashr(i32 %x) { 38; CHECK-LABEL: @positive_biggerashr( 39; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], 10 40; CHECK-NEXT: [[RET:%.*]] = shl nsw i32 [[TMP0]], 5 41; CHECK-NEXT: ret i32 [[RET]] 42; 43 %tmp0 = ashr i32 %x, 10 44 %ret = shl i32 %tmp0, 5 45 ret i32 %ret 46} 47 48define i32 @positive_biggershl(i32 %x) { 49; CHECK-LABEL: @positive_biggershl( 50; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 5 51; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP1]], 10 52; CHECK-NEXT: ret i32 [[RET]] 53; 54 %tmp0 = ashr i32 %x, 5 55 %ret = shl i32 %tmp0, 10 56 ret i32 %ret 57} 58 59; ============================================================================ ; 60; EXACT on the first shift 61; ============================================================================ ; 62 63define i32 @positive_samevar_ashrexact(i32 %x, i32 %y) { 64; CHECK-LABEL: @positive_samevar_ashrexact( 65; CHECK-NEXT: ret i32 [[X:%.*]] 66; 67 %tmp0 = ashr exact i32 %x, %y 68 %ret = shl i32 %tmp0, %y ; this one is obviously 'nuw'. 69 ret i32 %ret 70} 71 72define i32 @positive_sameconst_ashrexact(i32 %x) { 73; CHECK-LABEL: @positive_sameconst_ashrexact( 74; CHECK-NEXT: ret i32 [[X:%.*]] 75; 76 %tmp0 = ashr exact i32 %x, 5 77 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'. 78 ret i32 %ret 79} 80 81define i32 @positive_biggerashr_ashrexact(i32 %x) { 82; CHECK-LABEL: @positive_biggerashr_ashrexact( 83; CHECK-NEXT: [[RET:%.*]] = ashr exact i32 [[X:%.*]], 5 84; CHECK-NEXT: ret i32 [[RET]] 85; 86 %tmp0 = ashr exact i32 %x, 10 87 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'. 88 ret i32 %ret 89} 90 91define i32 @positive_biggershl_ashrexact(i32 %x) { 92; CHECK-LABEL: @positive_biggershl_ashrexact( 93; CHECK-NEXT: [[RET:%.*]] = shl i32 [[X:%.*]], 5 94; CHECK-NEXT: ret i32 [[RET]] 95; 96 %tmp0 = ashr exact i32 %x, 5 97 %ret = shl i32 %tmp0, 10 98 ret i32 %ret 99} 100 101define i32 @positive_biggershl_ashrexact_shlnuw(i32 %x) { 102; CHECK-LABEL: @positive_biggershl_ashrexact_shlnuw( 103; CHECK-NEXT: [[RET:%.*]] = shl nuw i32 [[X:%.*]], 5 104; CHECK-NEXT: ret i32 [[RET]] 105; 106 %tmp0 = ashr exact i32 %x, 5 107 %ret = shl nuw i32 %tmp0, 10 108 ret i32 %ret 109} 110 111; ============================================================================ ; 112; Vector 113; ============================================================================ ; 114 115define <2 x i32> @positive_samevar_vec(<2 x i32> %x, <2 x i32> %y) { 116; CHECK-LABEL: @positive_samevar_vec( 117; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 -1, i32 -1>, [[Y:%.*]] 118; CHECK-NEXT: [[RET:%.*]] = and <2 x i32> [[TMP1]], [[X:%.*]] 119; CHECK-NEXT: ret <2 x i32> [[RET]] 120; 121 %tmp0 = ashr <2 x i32> %x, %y 122 %ret = shl <2 x i32> %tmp0, %y 123 ret <2 x i32> %ret 124} 125 126; ============================================================================ ; 127; Constant Vectors 128; ============================================================================ ; 129 130define <2 x i32> @positive_sameconst_vec(<2 x i32> %x) { 131; CHECK-LABEL: @positive_sameconst_vec( 132; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -32, i32 -32> 133; CHECK-NEXT: ret <2 x i32> [[TMP1]] 134; 135 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 136 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 137 ret <2 x i32> %ret 138} 139 140define <3 x i32> @positive_sameconst_vec_undef0(<3 x i32> %x) { 141; CHECK-LABEL: @positive_sameconst_vec_undef0( 142; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 143; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5> 144; CHECK-NEXT: ret <3 x i32> [[RET]] 145; 146 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 147 %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5> 148 ret <3 x i32> %ret 149} 150 151define <3 x i32> @positive_sameconst_vec_undef1(<3 x i32> %x) { 152; CHECK-LABEL: @positive_sameconst_vec_undef1( 153; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5> 154; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 155; CHECK-NEXT: ret <3 x i32> [[RET]] 156; 157 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5> 158 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 159 ret <3 x i32> %ret 160} 161 162define <3 x i32> @positive_sameconst_vec_undef2(<3 x i32> %x) { 163; CHECK-LABEL: @positive_sameconst_vec_undef2( 164; CHECK-NEXT: [[RET:%.*]] = and <3 x i32> [[X:%.*]], <i32 -32, i32 undef, i32 -32> 165; CHECK-NEXT: ret <3 x i32> [[RET]] 166; 167 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 168 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 169 ret <3 x i32> %ret 170} 171 172define <2 x i32> @positive_biggerashr_vec(<2 x i32> %x) { 173; CHECK-LABEL: @positive_biggerashr_vec( 174; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 10, i32 10> 175; CHECK-NEXT: [[RET:%.*]] = shl nsw <2 x i32> [[TMP0]], <i32 5, i32 5> 176; CHECK-NEXT: ret <2 x i32> [[RET]] 177; 178 %tmp0 = ashr <2 x i32> %x, <i32 10, i32 10> 179 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 180 ret <2 x i32> %ret 181} 182 183define <3 x i32> @positive_biggerashr_vec_undef0(<3 x i32> %x) { 184; CHECK-LABEL: @positive_biggerashr_vec_undef0( 185; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10> 186; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5> 187; CHECK-NEXT: ret <3 x i32> [[RET]] 188; 189 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10> 190 %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5> 191 ret <3 x i32> %ret 192} 193 194define <3 x i32> @positive_biggerashr_vec_undef1(<3 x i32> %x) { 195; CHECK-LABEL: @positive_biggerashr_vec_undef1( 196; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 10, i32 10> 197; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 198; CHECK-NEXT: ret <3 x i32> [[RET]] 199; 200 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 10, i32 10> 201 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 202 ret <3 x i32> %ret 203} 204 205define <3 x i32> @positive_biggerashr_vec_undef2(<3 x i32> %x) { 206; CHECK-LABEL: @positive_biggerashr_vec_undef2( 207; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10> 208; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 209; CHECK-NEXT: ret <3 x i32> [[RET]] 210; 211 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10> 212 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 213 ret <3 x i32> %ret 214} 215 216define <2 x i32> @positive_biggershl_vec(<2 x i32> %x) { 217; CHECK-LABEL: @positive_biggershl_vec( 218; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 5> 219; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP1]], <i32 10, i32 10> 220; CHECK-NEXT: ret <2 x i32> [[RET]] 221; 222 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 223 %ret = shl <2 x i32> %tmp0, <i32 10, i32 10> 224 ret <2 x i32> %ret 225} 226 227define <3 x i32> @positive_biggershl_vec_undef0(<3 x i32> %x) { 228; CHECK-LABEL: @positive_biggershl_vec_undef0( 229; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 230; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 10, i32 10> 231; CHECK-NEXT: ret <3 x i32> [[RET]] 232; 233 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 234 %ret = shl <3 x i32> %tmp0, <i32 10, i32 10, i32 10> 235 ret <3 x i32> %ret 236} 237 238define <3 x i32> @positive_biggershl_vec_undef1(<3 x i32> %x) { 239; CHECK-LABEL: @positive_biggershl_vec_undef1( 240; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5> 241; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10> 242; CHECK-NEXT: ret <3 x i32> [[RET]] 243; 244 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5> 245 %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10> 246 ret <3 x i32> %ret 247} 248 249define <3 x i32> @positive_biggershl_vec_undef2(<3 x i32> %x) { 250; CHECK-LABEL: @positive_biggershl_vec_undef2( 251; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 252; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10> 253; CHECK-NEXT: ret <3 x i32> [[RET]] 254; 255 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 256 %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10> 257 ret <3 x i32> %ret 258} 259 260; ============================================================================ ; 261; Positive multi-use tests with constant 262; ============================================================================ ; 263 264; FIXME: drop 'exact' once it is no longer needed. 265 266define i32 @positive_sameconst_multiuse(i32 %x) { 267; CHECK-LABEL: @positive_sameconst_multiuse( 268; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5 269; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 270; CHECK-NEXT: ret i32 [[X]] 271; 272 %tmp0 = ashr exact i32 %x, 5 273 call void @use32(i32 %tmp0) 274 %ret = shl i32 %tmp0, 5 275 ret i32 %ret 276} 277 278define i32 @positive_biggerashr_multiuse(i32 %x) { 279; CHECK-LABEL: @positive_biggerashr_multiuse( 280; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 10 281; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 282; CHECK-NEXT: [[RET:%.*]] = ashr exact i32 [[X]], 5 283; CHECK-NEXT: ret i32 [[RET]] 284; 285 %tmp0 = ashr exact i32 %x, 10 286 call void @use32(i32 %tmp0) 287 %ret = shl i32 %tmp0, 5 288 ret i32 %ret 289} 290 291define i32 @positive_biggershl_multiuse(i32 %x) { 292; CHECK-LABEL: @positive_biggershl_multiuse( 293; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5 294; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 295; CHECK-NEXT: [[RET:%.*]] = shl i32 [[X]], 5 296; CHECK-NEXT: ret i32 [[RET]] 297; 298 %tmp0 = ashr exact i32 %x, 5 299 call void @use32(i32 %tmp0) 300 %ret = shl i32 %tmp0, 10 301 ret i32 %ret 302} 303 304; ============================================================================ ; 305; Constant Non-Splat Vectors 306; ============================================================================ ; 307 308define <2 x i32> @positive_biggerashr_vec_nonsplat(<2 x i32> %x) { 309; CHECK-LABEL: @positive_biggerashr_vec_nonsplat( 310; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 5> 311; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 10> 312; CHECK-NEXT: ret <2 x i32> [[RET]] 313; 314 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 315 %ret = shl <2 x i32> %tmp0, <i32 5, i32 10> 316 ret <2 x i32> %ret 317} 318 319define <2 x i32> @positive_biggerLashr_vec_nonsplat(<2 x i32> %x) { 320; CHECK-LABEL: @positive_biggerLashr_vec_nonsplat( 321; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 10> 322; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 5> 323; CHECK-NEXT: ret <2 x i32> [[RET]] 324; 325 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 10> 326 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 327 ret <2 x i32> %ret 328} 329 330; ============================================================================ ; 331; Negative tests. Should not be folded. 332; ============================================================================ ; 333 334define i32 @negative_twovars(i32 %x, i32 %y, i32 %z) { 335; CHECK-LABEL: @negative_twovars( 336; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]] 337; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP0]], [[Z:%.*]] 338; CHECK-NEXT: ret i32 [[RET]] 339; 340 %tmp0 = ashr i32 %x, %y 341 %ret = shl i32 %tmp0, %z ; $z, not %y 342 ret i32 %ret 343} 344 345declare void @use32(i32) 346 347; One use only. 348define i32 @negative_oneuse(i32 %x, i32 %y) { 349; CHECK-LABEL: @negative_oneuse( 350; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]] 351; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 352; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP0]], [[Y]] 353; CHECK-NEXT: ret i32 [[RET]] 354; 355 %tmp0 = ashr i32 %x, %y 356 call void @use32(i32 %tmp0) 357 %ret = shl i32 %tmp0, %y 358 ret i32 %ret 359} 360