• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; If we have some pattern that leaves only some low bits set, and then performs
5; left-shift of those bits, we can combine those two shifts into a shift+mask.
6
7; There are many variants to this pattern:
8;   e)  ((x << maskNbits) l>> maskNbits) << shiftNbits
9; simplify to:
10;   (x << shiftNbits) & (-1 >> ((-(maskNbits+shiftNbits))+32))
11
12; Simple tests.
13
14declare void @use32(i32)
15
16define i32 @t0_basic(i32 %x, i32 %nbits) {
17; CHECK-LABEL: @t0_basic(
18; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
19; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -1
20; CHECK-NEXT:    call void @use32(i32 [[T0]])
21; CHECK-NEXT:    call void @use32(i32 [[T2]])
22; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X]], [[T2]]
23; CHECK-NEXT:    [[T3:%.*]] = and i32 [[TMP1]], 2147483647
24; CHECK-NEXT:    ret i32 [[T3]]
25;
26  %t0 = shl i32 %x, %nbits
27  %t1 = lshr i32 %t0, %nbits
28  %t2 = add i32 %nbits, -1
29  call void @use32(i32 %t0)
30  call void @use32(i32 %t2)
31  %t3 = shl i32 %t1, %t2 ; shift is smaller than mask
32  ret i32 %t3
33}
34
35; Vectors
36
37declare void @use8xi32(<8 x i32>)
38
39define <8 x i32> @t1_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {
40; CHECK-LABEL: @t1_vec_splat(
41; CHECK-NEXT:    [[T0:%.*]] = shl <8 x i32> [[X:%.*]], [[NBITS:%.*]]
42; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
43; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
44; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
45; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X]], [[T2]]
46; CHECK-NEXT:    [[T3:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
47; CHECK-NEXT:    ret <8 x i32> [[T3]]
48;
49  %t0 = shl <8 x i32> %x, %nbits
50  %t1 = lshr <8 x i32> %t0, %nbits
51  %t2 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
52  call void @use8xi32(<8 x i32> %t0)
53  call void @use8xi32(<8 x i32> %t2)
54  %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask
55  ret <8 x i32> %t3
56}
57
58define <8 x i32> @t1_vec_splat_undef(<8 x i32> %x, <8 x i32> %nbits) {
59; CHECK-LABEL: @t1_vec_splat_undef(
60; CHECK-NEXT:    [[T0:%.*]] = shl <8 x i32> [[X:%.*]], [[NBITS:%.*]]
61; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
62; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
63; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
64; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X]], [[T2]]
65; CHECK-NEXT:    [[T3:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>
66; CHECK-NEXT:    ret <8 x i32> [[T3]]
67;
68  %t0 = shl <8 x i32> %x, %nbits
69  %t1 = lshr <8 x i32> %t0, %nbits
70  %t2 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
71  call void @use8xi32(<8 x i32> %t0)
72  call void @use8xi32(<8 x i32> %t2)
73  %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask
74  ret <8 x i32> %t3
75}
76
77define <8 x i32> @t1_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {
78; CHECK-LABEL: @t1_vec_nonsplat(
79; CHECK-NEXT:    [[T0:%.*]] = shl <8 x i32> [[X:%.*]], [[NBITS:%.*]]
80; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
81; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
82; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
83; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X]], [[T2]]
84; CHECK-NEXT:    [[T3:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison>
85; CHECK-NEXT:    ret <8 x i32> [[T3]]
86;
87  %t0 = shl <8 x i32> %x, %nbits
88  %t1 = lshr <8 x i32> %t0, %nbits
89  %t2 = add <8 x i32> %nbits, <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
90  call void @use8xi32(<8 x i32> %t0)
91  call void @use8xi32(<8 x i32> %t2)
92  %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask
93  ret <8 x i32> %t3
94}
95
96; Extra uses.
97
98define i32 @n3_extrause(i32 %x, i32 %nbits) {
99; CHECK-LABEL: @n3_extrause(
100; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
101; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
102; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -1
103; CHECK-NEXT:    call void @use32(i32 [[T0]])
104; CHECK-NEXT:    call void @use32(i32 [[T1]])
105; CHECK-NEXT:    call void @use32(i32 [[T2]])
106; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[T1]], [[T2]]
107; CHECK-NEXT:    ret i32 [[T3]]
108;
109  %t0 = shl i32 %x, %nbits
110  %t1 = lshr i32 %t0, %nbits
111  %t2 = add i32 %nbits, -1
112  call void @use32(i32 %t0)
113  call void @use32(i32 %t1) ; BAD
114  call void @use32(i32 %t2)
115  %t3 = shl i32 %t1, %t2 ; shift is smaller than mask
116  ret i32 %t3
117}
118