1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; Simplify 'shl' inequality test into 'and' equality test. 5; (X l<< C2) u</u>= C1 iff C1 is power of 2 -> X & (-C1 l>> C2) ==/!= 0 6 7; Scalar tests 8 9; C2 Shift amount smaller than C1 trailing zeros. 10define i1 @scalar_i8_shl_ult_const_1(i8 %x) { 11; CHECK-LABEL: @scalar_i8_shl_ult_const_1( 12; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 6 13; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0 14; CHECK-NEXT: ret i1 [[CMP]] 15; 16 %shl = shl i8 %x, 5 17 %cmp = icmp ult i8 %shl, 64 18 ret i1 %cmp 19} 20 21; C2 Shift amount equal to C1 trailing zeros. 22define i1 @scalar_i8_shl_ult_const_2(i8 %x) { 23; CHECK-LABEL: @scalar_i8_shl_ult_const_2( 24; CHECK-NEXT: [[SHL_MASK:%.*]] = and i8 [[X:%.*]], 3 25; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 0 26; CHECK-NEXT: ret i1 [[CMP]] 27; 28 %shl = shl i8 %x, 6 29 %cmp = icmp ult i8 %shl, 64 30 ret i1 %cmp 31} 32 33; C2 Shift amount greater than C1 trailing zeros. 34define i1 @scalar_i8_shl_ult_const_3(i8 %x) { 35; CHECK-LABEL: @scalar_i8_shl_ult_const_3( 36; CHECK-NEXT: [[SHL_MASK:%.*]] = and i8 [[X:%.*]], 1 37; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 0 38; CHECK-NEXT: ret i1 [[CMP]] 39; 40 %shl = shl i8 %x, 7 41 %cmp = icmp ult i8 %shl, 64 42 ret i1 %cmp 43} 44 45; C2 Shift amount smaller than C1 trailing zeros. 46define i1 @scalar_i16_shl_ult_const(i16 %x) { 47; CHECK-LABEL: @scalar_i16_shl_ult_const( 48; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], 252 49; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP1]], 0 50; CHECK-NEXT: ret i1 [[CMP]] 51; 52 %shl = shl i16 %x, 8 53 %cmp = icmp ult i16 %shl, 1024 54 ret i1 %cmp 55} 56 57define i1 @scalar_i32_shl_ult_const(i32 %x) { 58; CHECK-LABEL: @scalar_i32_shl_ult_const( 59; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 2097088 60; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0 61; CHECK-NEXT: ret i1 [[CMP]] 62; 63 %shl = shl i32 %x, 11 64 %cmp = icmp ult i32 %shl, 131072 65 ret i1 %cmp 66} 67 68define i1 @scalar_i64_shl_ult_const(i64 %x) { 69; CHECK-LABEL: @scalar_i64_shl_ult_const( 70; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 549755813632 71; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], 0 72; CHECK-NEXT: ret i1 [[CMP]] 73; 74 %shl = shl i64 %x, 25 75 %cmp = icmp ult i64 %shl, 8589934592 76 ret i1 %cmp 77} 78 79; Check 'uge' predicate 80define i1 @scalar_i8_shl_uge_const(i8 %x) { 81; CHECK-LABEL: @scalar_i8_shl_uge_const( 82; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 6 83; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0 84; CHECK-NEXT: ret i1 [[CMP]] 85; 86 %shl = shl i8 %x, 5 87 %cmp = icmp uge i8 %shl, 64 88 ret i1 %cmp 89} 90 91; Check 'ule' predicate 92define i1 @scalar_i8_shl_ule_const(i8 %x) { 93; CHECK-LABEL: @scalar_i8_shl_ule_const( 94; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 6 95; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0 96; CHECK-NEXT: ret i1 [[CMP]] 97; 98 %shl = shl i8 %x, 5 99 %cmp = icmp ule i8 %shl, 63 100 ret i1 %cmp 101} 102 103; Check 'ugt' predicate 104define i1 @scalar_i8_shl_ugt_const(i8 %x) { 105; CHECK-LABEL: @scalar_i8_shl_ugt_const( 106; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 6 107; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0 108; CHECK-NEXT: ret i1 [[CMP]] 109; 110 %shl = shl i8 %x, 5 111 %cmp = icmp ugt i8 %shl, 63 112 ret i1 %cmp 113} 114 115; Vector tests 116 117define <4 x i1> @vector_4xi32_shl_ult_const(<4 x i32> %x) { 118; CHECK-LABEL: @vector_4xi32_shl_ult_const( 119; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088> 120; CHECK-NEXT: [[CMP:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer 121; CHECK-NEXT: ret <4 x i1> [[CMP]] 122; 123 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11> 124 %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072> 125 ret <4 x i1> %cmp 126} 127 128define <4 x i1> @vector_4xi32_shl_ult_const_undef1(<4 x i32> %x) { 129; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef1( 130; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 undef, i32 11> 131; CHECK-NEXT: [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 131072, i32 131072, i32 131072, i32 131072> 132; CHECK-NEXT: ret <4 x i1> [[CMP]] 133; 134 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 undef, i32 11> 135 %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072> 136 ret <4 x i1> %cmp 137} 138 139define <4 x i1> @vector_4xi32_shl_ult_const_undef2(<4 x i32> %x) { 140; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef2( 141; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 11, i32 11> 142; CHECK-NEXT: [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 131072, i32 131072, i32 131072, i32 undef> 143; CHECK-NEXT: ret <4 x i1> [[CMP]] 144; 145 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11> 146 %cmp = icmp ult <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 undef> 147 ret <4 x i1> %cmp 148} 149 150define <4 x i1> @vector_4xi32_shl_ult_const_undef3(<4 x i32> %x) { 151; CHECK-LABEL: @vector_4xi32_shl_ult_const_undef3( 152; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], <i32 11, i32 11, i32 undef, i32 11> 153; CHECK-NEXT: [[CMP:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 undef, i32 131072, i32 131072, i32 131072> 154; CHECK-NEXT: ret <4 x i1> [[CMP]] 155; 156 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 undef, i32 11> 157 %cmp = icmp ult <4 x i32> %shl, <i32 undef, i32 131072, i32 131072, i32 131072> 158 ret <4 x i1> %cmp 159} 160 161; Check 'uge' predicate 162define <4 x i1> @vector_4xi32_shl_uge_const(<4 x i32> %x) { 163; CHECK-LABEL: @vector_4xi32_shl_uge_const( 164; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088> 165; CHECK-NEXT: [[CMP:%.*]] = icmp ne <4 x i32> [[TMP1]], zeroinitializer 166; CHECK-NEXT: ret <4 x i1> [[CMP]] 167; 168 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11> 169 %cmp = icmp uge <4 x i32> %shl, <i32 131072, i32 131072, i32 131072, i32 131072> 170 ret <4 x i1> %cmp 171} 172 173; Check 'ule' predicate 174define <4 x i1> @vector_4xi32_shl_ule_const(<4 x i32> %x) { 175; CHECK-LABEL: @vector_4xi32_shl_ule_const( 176; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088> 177; CHECK-NEXT: [[CMP:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer 178; CHECK-NEXT: ret <4 x i1> [[CMP]] 179; 180 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11> 181 %cmp = icmp ule <4 x i32> %shl, <i32 131071, i32 131071, i32 131071, i32 131071> 182 ret <4 x i1> %cmp 183} 184 185; Check 'ugt' predicate 186define <4 x i1> @vector_4xi32_shl_ugt_const(<4 x i32> %x) { 187; CHECK-LABEL: @vector_4xi32_shl_ugt_const( 188; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[X:%.*]], <i32 2097088, i32 2097088, i32 2097088, i32 2097088> 189; CHECK-NEXT: [[CMP:%.*]] = icmp ne <4 x i32> [[TMP1]], zeroinitializer 190; CHECK-NEXT: ret <4 x i1> [[CMP]] 191; 192 %shl = shl <4 x i32> %x, <i32 11, i32 11, i32 11, i32 11> 193 %cmp = icmp ugt <4 x i32> %shl, <i32 131071, i32 131071, i32 131071, i32 131071> 194 ret <4 x i1> %cmp 195} 196 197; Extra use 198 199; Not simplified 200define i1 @scalar_i8_shl_ult_const_extra_use_shl(i8 %x, i8* %p) { 201; CHECK-LABEL: @scalar_i8_shl_ult_const_extra_use_shl( 202; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], 5 203; CHECK-NEXT: store i8 [[SHL]], i8* [[P:%.*]], align 1 204; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[SHL]], 64 205; CHECK-NEXT: ret i1 [[CMP]] 206; 207 %shl = shl i8 %x, 5 208 store i8 %shl, i8* %p 209 %cmp = icmp ult i8 %shl, 64 210 ret i1 %cmp 211} 212 213; Negative tests 214 215; Check 'slt' predicate 216define i1 @scalar_i8_shl_slt_const(i8 %x) { 217; CHECK-LABEL: @scalar_i8_shl_slt_const( 218; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], 5 219; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SHL]], 64 220; CHECK-NEXT: ret i1 [[CMP]] 221; 222 %shl = shl i8 %x, 5 223 %cmp = icmp slt i8 %shl, 64 224 ret i1 %cmp 225} 226 227define i1 @scalar_i8_shl_ugt_const_not_power_of_2(i8 %x) { 228; CHECK-LABEL: @scalar_i8_shl_ugt_const_not_power_of_2( 229; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], 5 230; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SHL]], 66 231; CHECK-NEXT: ret i1 [[CMP]] 232; 233 %shl = shl i8 %x, 5 234 %cmp = icmp ugt i8 %shl, 66 235 ret i1 %cmp 236} 237