1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Iff we know that trunc only chops off the sign bits, 5; and not all of them, then we can bypass said trunc 6; for the purpose of sign extension. 7 8declare void @use8(i8) 9declare void @use4(i4) 10declare void @usevec(<2 x i8>) 11 12define i16 @t0(i8 %x) { 13; CHECK-LABEL: @t0( 14; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 5 15; CHECK-NEXT: call void @use8(i8 [[A]]) 16; CHECK-NEXT: [[C:%.*]] = sext i8 [[A]] to i16 17; CHECK-NEXT: ret i16 [[C]] 18; 19 %a = ashr i8 %x, 5 20 call void @use8(i8 %a) 21 %b = trunc i8 %a to i4 22 %c = sext i4 %b to i16 23 ret i16 %c 24} 25 26define i16 @t1(i8 %x) { 27; CHECK-LABEL: @t1( 28; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 4 29; CHECK-NEXT: call void @use8(i8 [[A]]) 30; CHECK-NEXT: [[C:%.*]] = sext i8 [[A]] to i16 31; CHECK-NEXT: ret i16 [[C]] 32; 33 %a = ashr i8 %x, 4 34 call void @use8(i8 %a) 35 %b = trunc i8 %a to i4 36 %c = sext i4 %b to i16 37 ret i16 %c 38} 39 40; Here we don't know that %a has any sign bits from %x left 41define i16 @n2(i8 %x) { 42; CHECK-LABEL: @n2( 43; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 3 44; CHECK-NEXT: call void @use8(i8 [[A]]) 45; CHECK-NEXT: [[B:%.*]] = trunc i8 [[A]] to i4 46; CHECK-NEXT: [[C:%.*]] = sext i4 [[B]] to i16 47; CHECK-NEXT: ret i16 [[C]] 48; 49 %a = ashr i8 %x, 3 50 call void @use8(i8 %a) 51 %b = trunc i8 %a to i4 52 %c = sext i4 %b to i16 53 ret i16 %c 54} 55 56define <2 x i16> @t3_vec(<2 x i8> %x) { 57; CHECK-LABEL: @t3_vec( 58; CHECK-NEXT: [[A:%.*]] = ashr <2 x i8> [[X:%.*]], splat (i8 4) 59; CHECK-NEXT: call void @usevec(<2 x i8> [[A]]) 60; CHECK-NEXT: [[C:%.*]] = sext <2 x i8> [[A]] to <2 x i16> 61; CHECK-NEXT: ret <2 x i16> [[C]] 62; 63 %a = ashr <2 x i8> %x, <i8 4, i8 4> 64 call void @usevec(<2 x i8> %a) 65 %b = trunc <2 x i8> %a to <2 x i4> 66 %c = sext <2 x i4> %b to <2 x i16> 67 ret <2 x i16> %c 68} 69 70define <2 x i16> @t4_vec_nonsplat(<2 x i8> %x) { 71; CHECK-LABEL: @t4_vec_nonsplat( 72; CHECK-NEXT: [[A:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 4, i8 3> 73; CHECK-NEXT: call void @usevec(<2 x i8> [[A]]) 74; CHECK-NEXT: [[B:%.*]] = trunc <2 x i8> [[A]] to <2 x i4> 75; CHECK-NEXT: [[C:%.*]] = sext <2 x i4> [[B]] to <2 x i16> 76; CHECK-NEXT: ret <2 x i16> [[C]] 77; 78 %a = ashr <2 x i8> %x, <i8 4, i8 3> 79 call void @usevec(<2 x i8> %a) 80 %b = trunc <2 x i8> %a to <2 x i4> 81 %c = sext <2 x i4> %b to <2 x i16> 82 ret <2 x i16> %c 83} 84 85define i16 @t5_extrause(i8 %x) { 86; CHECK-LABEL: @t5_extrause( 87; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 5 88; CHECK-NEXT: call void @use8(i8 [[A]]) 89; CHECK-NEXT: [[B:%.*]] = trunc nsw i8 [[A]] to i4 90; CHECK-NEXT: call void @use4(i4 [[B]]) 91; CHECK-NEXT: [[C:%.*]] = sext i8 [[A]] to i16 92; CHECK-NEXT: ret i16 [[C]] 93; 94 %a = ashr i8 %x, 5 95 call void @use8(i8 %a) 96 %b = trunc i8 %a to i4 97 call void @use4(i4 %b) 98 %c = sext i4 %b to i16 99 ret i16 %c 100} 101 102define i64 @narrow_source_matching_signbits(i32 %x) { 103; CHECK-LABEL: @narrow_source_matching_signbits( 104; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 7 105; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M]] 106; CHECK-NEXT: [[C:%.*]] = sext i32 [[A]] to i64 107; CHECK-NEXT: ret i64 [[C]] 108; 109 %m = and i32 %x, 7 110 %a = shl nsw i32 -1, %m 111 %b = trunc i32 %a to i8 112 %c = sext i8 %b to i64 113 ret i64 %c 114} 115 116; negative test - not enough sign-bits 117 118define i64 @narrow_source_not_matching_signbits(i32 %x) { 119; CHECK-LABEL: @narrow_source_not_matching_signbits( 120; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 8 121; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M]] 122; CHECK-NEXT: [[B:%.*]] = trunc i32 [[A]] to i8 123; CHECK-NEXT: [[C:%.*]] = sext i8 [[B]] to i64 124; CHECK-NEXT: ret i64 [[C]] 125; 126 %m = and i32 %x, 8 127 %a = shl nsw i32 -1, %m 128 %b = trunc i32 %a to i8 129 %c = sext i8 %b to i64 130 ret i64 %c 131} 132 133define i24 @wide_source_matching_signbits(i32 %x) { 134; CHECK-LABEL: @wide_source_matching_signbits( 135; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 7 136; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M]] 137; CHECK-NEXT: [[C:%.*]] = trunc nsw i32 [[A]] to i24 138; CHECK-NEXT: ret i24 [[C]] 139; 140 %m = and i32 %x, 7 141 %a = shl nsw i32 -1, %m 142 %b = trunc i32 %a to i8 143 %c = sext i8 %b to i24 144 ret i24 %c 145} 146 147; negative test - not enough sign-bits 148 149define i24 @wide_source_not_matching_signbits(i32 %x) { 150; CHECK-LABEL: @wide_source_not_matching_signbits( 151; CHECK-NEXT: [[M2:%.*]] = and i32 [[X:%.*]], 8 152; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M2]] 153; CHECK-NEXT: [[B:%.*]] = trunc i32 [[A]] to i8 154; CHECK-NEXT: [[C:%.*]] = sext i8 [[B]] to i24 155; CHECK-NEXT: ret i24 [[C]] 156; 157 %m2 = and i32 %x, 8 158 %a = shl nsw i32 -1, %m2 159 %b = trunc i32 %a to i8 160 %c = sext i8 %b to i24 161 ret i24 %c 162} 163 164define i32 @same_source_matching_signbits(i32 %x) { 165; CHECK-LABEL: @same_source_matching_signbits( 166; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 7 167; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M]] 168; CHECK-NEXT: ret i32 [[A]] 169; 170 %m = and i32 %x, 7 171 %a = shl nsw i32 -1, %m 172 %b = trunc i32 %a to i8 173 %c = sext i8 %b to i32 174 ret i32 %c 175} 176 177; negative test - not enough sign-bits 178 179define i32 @same_source_not_matching_signbits(i32 %x) { 180; CHECK-LABEL: @same_source_not_matching_signbits( 181; CHECK-NEXT: [[M2:%.*]] = and i32 [[X:%.*]], 8 182; CHECK-NEXT: [[TMP1:%.*]] = shl i32 -16777216, [[M2]] 183; CHECK-NEXT: [[C:%.*]] = ashr exact i32 [[TMP1]], 24 184; CHECK-NEXT: ret i32 [[C]] 185; 186 %m2 = and i32 %x, 8 187 %a = shl nsw i32 -1, %m2 188 %b = trunc i32 %a to i8 189 %c = sext i8 %b to i32 190 ret i32 %c 191} 192 193define i32 @same_source_matching_signbits_extra_use(i32 %x) { 194; CHECK-LABEL: @same_source_matching_signbits_extra_use( 195; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 7 196; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M]] 197; CHECK-NEXT: [[B:%.*]] = trunc nsw i32 [[A]] to i8 198; CHECK-NEXT: call void @use8(i8 [[B]]) 199; CHECK-NEXT: ret i32 [[A]] 200; 201 %m = and i32 %x, 7 202 %a = shl nsw i32 -1, %m 203 %b = trunc i32 %a to i8 204 call void @use8(i8 %b) 205 %c = sext i8 %b to i32 206 ret i32 %c 207} 208 209define i32 @same_source_not_matching_signbits_extra_use(i32 %x) { 210; CHECK-LABEL: @same_source_not_matching_signbits_extra_use( 211; CHECK-NEXT: [[M2:%.*]] = and i32 [[X:%.*]], 8 212; CHECK-NEXT: [[A:%.*]] = shl nsw i32 -1, [[M2]] 213; CHECK-NEXT: [[B:%.*]] = trunc i32 [[A]] to i8 214; CHECK-NEXT: call void @use8(i8 [[B]]) 215; CHECK-NEXT: [[C:%.*]] = sext i8 [[B]] to i32 216; CHECK-NEXT: ret i32 [[C]] 217; 218 %m2 = and i32 %x, 8 219 %a = shl nsw i32 -1, %m2 220 %b = trunc i32 %a to i8 221 call void @use8(i8 %b) 222 %c = sext i8 %b to i32 223 ret i32 %c 224} 225