1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5declare void @use(i8) 6declare void @use16(i16) 7 8define i1 @testi16i8(i16 %add) { 9; CHECK-LABEL: @testi16i8( 10; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128 11; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256 12; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 13; 14 %sh = lshr i16 %add, 8 15 %conv.i = trunc i16 %sh to i8 16 %conv1.i = trunc i16 %add to i8 17 %shr2.i = ashr i8 %conv1.i, 7 18 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 19 ret i1 %cmp.not.i 20} 21 22define i1 @testi16i8_com(i16 %add) { 23; CHECK-LABEL: @testi16i8_com( 24; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128 25; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256 26; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 27; 28 %sh = lshr i16 %add, 8 29 %conv.i = trunc i16 %sh to i8 30 %conv1.i = trunc i16 %add to i8 31 %shr2.i = ashr i8 %conv1.i, 7 32 %cmp.not.i = icmp eq i8 %conv.i, %shr2.i 33 ret i1 %cmp.not.i 34} 35 36define i1 @testi16i8_ne(i16 %add) { 37; CHECK-LABEL: @testi16i8_ne( 38; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], -128 39; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], -256 40; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 41; 42 %sh = lshr i16 %add, 8 43 %conv.i = trunc i16 %sh to i8 44 %conv1.i = trunc i16 %add to i8 45 %shr2.i = ashr i8 %conv1.i, 7 46 %cmp.not.i = icmp ne i8 %shr2.i, %conv.i 47 ret i1 %cmp.not.i 48} 49 50define i1 @testi16i8_ne_com(i16 %add) { 51; CHECK-LABEL: @testi16i8_ne_com( 52; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], -128 53; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], -256 54; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 55; 56 %sh = lshr i16 %add, 8 57 %conv.i = trunc i16 %sh to i8 58 %conv1.i = trunc i16 %add to i8 59 %shr2.i = ashr i8 %conv1.i, 7 60 %cmp.not.i = icmp ne i8 %conv.i, %shr2.i 61 ret i1 %cmp.not.i 62} 63 64define i1 @testi64i32(i64 %add) { 65; CHECK-LABEL: @testi64i32( 66; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[ADD:%.*]], 2147483648 67; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i64 [[TMP1]], 4294967296 68; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 69; 70 %sh = lshr i64 %add, 32 71 %conv.i = trunc i64 %sh to i32 72 %conv1.i = trunc i64 %add to i32 73 %shr2.i = ashr i32 %conv1.i, 31 74 %cmp.not.i = icmp eq i32 %shr2.i, %conv.i 75 ret i1 %cmp.not.i 76} 77 78define i1 @testi64i32_ne(i64 %add) { 79; CHECK-LABEL: @testi64i32_ne( 80; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[ADD:%.*]], -2147483648 81; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i64 [[TMP1]], -4294967296 82; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 83; 84 %sh = lshr i64 %add, 32 85 %conv.i = trunc i64 %sh to i32 86 %conv1.i = trunc i64 %add to i32 87 %shr2.i = ashr i32 %conv1.i, 31 88 %cmp.not.i = icmp ne i32 %shr2.i, %conv.i 89 ret i1 %cmp.not.i 90} 91 92; Negative tests 93 94define i1 @testi32i8(i32 %add) { 95; CHECK-LABEL: @testi32i8( 96; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[ADD:%.*]], 8 97; CHECK-NEXT: [[CONV_I:%.*]] = trunc i32 [[SH]] to i8 98; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i32 [[ADD]] to i8 99; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7 100; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]] 101; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 102; 103 %sh = lshr i32 %add, 8 104 %conv.i = trunc i32 %sh to i8 105 %conv1.i = trunc i32 %add to i8 106 %shr2.i = ashr i8 %conv1.i, 7 107 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 108 ret i1 %cmp.not.i 109} 110 111define i1 @wrongimm1(i16 %add) { 112; CHECK-LABEL: @wrongimm1( 113; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 7 114; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8 115; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8 116; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7 117; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]] 118; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 119; 120 %sh = lshr i16 %add, 7 121 %conv.i = trunc i16 %sh to i8 122 %conv1.i = trunc i16 %add to i8 123 %shr2.i = ashr i8 %conv1.i, 7 124 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 125 ret i1 %cmp.not.i 126} 127 128define i1 @wrongimm2(i16 %add) { 129; CHECK-LABEL: @wrongimm2( 130; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8 131; CHECK-NEXT: [[CONV_I:%.*]] = trunc nuw i16 [[SH]] to i8 132; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8 133; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 6 134; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]] 135; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 136; 137 %sh = lshr i16 %add, 8 138 %conv.i = trunc i16 %sh to i8 139 %conv1.i = trunc i16 %add to i8 140 %shr2.i = ashr i8 %conv1.i, 6 141 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 142 ret i1 %cmp.not.i 143} 144 145define i1 @slt(i64 %add) { 146; CHECK-LABEL: @slt( 147; CHECK-NEXT: [[SH:%.*]] = lshr i64 [[ADD:%.*]], 32 148; CHECK-NEXT: [[CONV_I:%.*]] = trunc nuw i64 [[SH]] to i32 149; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32 150; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31 151; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp slt i32 [[SHR2_I]], [[CONV_I]] 152; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 153; 154 %sh = lshr i64 %add, 32 155 %conv.i = trunc i64 %sh to i32 156 %conv1.i = trunc i64 %add to i32 157 %shr2.i = ashr i32 %conv1.i, 31 158 %cmp.not.i = icmp slt i32 %shr2.i, %conv.i 159 ret i1 %cmp.not.i 160} 161 162; Use checks 163 164define i1 @extrause_a(i16 %add) { 165; CHECK-LABEL: @extrause_a( 166; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD:%.*]] to i8 167; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7 168; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD]], 128 169; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256 170; CHECK-NEXT: call void @use(i8 [[SHR2_I]]) 171; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 172; 173 %sh = lshr i16 %add, 8 174 %conv.i = trunc i16 %sh to i8 175 %conv1.i = trunc i16 %add to i8 176 %shr2.i = ashr i8 %conv1.i, 7 177 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 178 call void @use(i8 %shr2.i) 179 ret i1 %cmp.not.i 180} 181 182define i1 @extrause_l(i16 %add) { 183; CHECK-LABEL: @extrause_l( 184; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8 185; CHECK-NEXT: [[CONV_I:%.*]] = trunc nuw i16 [[SH]] to i8 186; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD]], 128 187; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256 188; CHECK-NEXT: call void @use(i8 [[CONV_I]]) 189; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 190; 191 %sh = lshr i16 %add, 8 192 %conv.i = trunc i16 %sh to i8 193 %conv1.i = trunc i16 %add to i8 194 %shr2.i = ashr i8 %conv1.i, 7 195 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 196 call void @use(i8 %conv.i) 197 ret i1 %cmp.not.i 198} 199 200define i1 @extrause_la(i16 %add) { 201; CHECK-LABEL: @extrause_la( 202; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8 203; CHECK-NEXT: [[CONV_I:%.*]] = trunc nuw i16 [[SH]] to i8 204; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8 205; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7 206; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]] 207; CHECK-NEXT: call void @use(i8 [[SHR2_I]]) 208; CHECK-NEXT: call void @use(i8 [[CONV_I]]) 209; CHECK-NEXT: ret i1 [[CMP_NOT_I]] 210; 211 %sh = lshr i16 %add, 8 212 %conv.i = trunc i16 %sh to i8 213 %conv1.i = trunc i16 %add to i8 214 %shr2.i = ashr i8 %conv1.i, 7 215 %cmp.not.i = icmp eq i8 %shr2.i, %conv.i 216 call void @use(i8 %shr2.i) 217 call void @use(i8 %conv.i) 218 ret i1 %cmp.not.i 219} 220