1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=ANY,LE 3; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=ANY,BE 4 5define i32 @shrinkExtractElt_i64_to_i32_0(<3 x i64> %x) { 6; LE-LABEL: @shrinkExtractElt_i64_to_i32_0( 7; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 8; LE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 0 9; LE-NEXT: ret i32 [[T]] 10; 11; BE-LABEL: @shrinkExtractElt_i64_to_i32_0( 12; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 13; BE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 1 14; BE-NEXT: ret i32 [[T]] 15; 16 %e = extractelement <3 x i64> %x, i32 0 17 %t = trunc i64 %e to i32 18 ret i32 %t 19} 20 21define i32 @shrinkShiftExtractElt_i64_to_i32_0(<3 x i64> %x) { 22; LE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0( 23; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 24; LE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 1 25; LE-NEXT: ret i32 [[T]] 26; 27; BE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0( 28; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 29; BE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 0 30; BE-NEXT: ret i32 [[T]] 31; 32 %e = extractelement <3 x i64> %x, i32 0 33 %s = lshr i64 %e, 32 34 %t = trunc i64 %s to i32 35 ret i32 %t 36} 37 38define i32 @vscale_shrinkExtractElt_i64_to_i32_0(<vscale x 3 x i64> %x) { 39; LE-LABEL: @vscale_shrinkExtractElt_i64_to_i32_0( 40; LE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32> 41; LE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 0 42; LE-NEXT: ret i32 [[T]] 43; 44; BE-LABEL: @vscale_shrinkExtractElt_i64_to_i32_0( 45; BE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32> 46; BE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 1 47; BE-NEXT: ret i32 [[T]] 48; 49 %e = extractelement <vscale x 3 x i64> %x, i32 0 50 %t = trunc i64 %e to i32 51 ret i32 %t 52} 53 54define i32 @vscale_shrinkShiftExtractElt_i64_to_i32_0(<vscale x 3 x i64> %x) { 55; LE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0( 56; LE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32> 57; LE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 1 58; LE-NEXT: ret i32 [[T]] 59; 60; BE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0( 61; BE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32> 62; BE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 0 63; BE-NEXT: ret i32 [[T]] 64; 65 %e = extractelement <vscale x 3 x i64> %x, i32 0 66 %s = lshr i64 %e, 32 67 %t = trunc i64 %s to i32 68 ret i32 %t 69} 70 71define i32 @shrinkExtractElt_i64_to_i32_1(<3 x i64> %x) { 72; LE-LABEL: @shrinkExtractElt_i64_to_i32_1( 73; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 74; LE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 2 75; LE-NEXT: ret i32 [[T]] 76; 77; BE-LABEL: @shrinkExtractElt_i64_to_i32_1( 78; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 79; BE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 3 80; BE-NEXT: ret i32 [[T]] 81; 82 %e = extractelement <3 x i64> %x, i32 1 83 %t = trunc i64 %e to i32 84 ret i32 %t 85} 86 87define i32 @shrinkExtractElt_i64_to_i32_2(<3 x i64> %x) { 88; LE-LABEL: @shrinkExtractElt_i64_to_i32_2( 89; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 90; LE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 4 91; LE-NEXT: ret i32 [[T]] 92; 93; BE-LABEL: @shrinkExtractElt_i64_to_i32_2( 94; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32> 95; BE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 5 96; BE-NEXT: ret i32 [[T]] 97; 98 %e = extractelement <3 x i64> %x, i32 2 99 %t = trunc i64 %e to i32 100 ret i32 %t 101} 102 103define i16 @shrinkExtractElt_i64_to_i16_0(<3 x i64> %x) { 104; LE-LABEL: @shrinkExtractElt_i64_to_i16_0( 105; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 106; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 0 107; LE-NEXT: ret i16 [[T]] 108; 109; BE-LABEL: @shrinkExtractElt_i64_to_i16_0( 110; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 111; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 3 112; BE-NEXT: ret i16 [[T]] 113; 114 %e = extractelement <3 x i64> %x, i16 0 115 %t = trunc i64 %e to i16 116 ret i16 %t 117} 118 119define i16 @shrinkShiftExtractElt_i64_to_i16_0(<3 x i64> %x) { 120; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0( 121; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 122; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 3 123; LE-NEXT: ret i16 [[T]] 124; 125; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0( 126; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 127; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 0 128; BE-NEXT: ret i16 [[T]] 129; 130 %e = extractelement <3 x i64> %x, i16 0 131 %s = ashr i64 %e, 48 132 %t = trunc i64 %s to i16 133 ret i16 %t 134} 135 136define i16 @shrinkExtractElt_i64_to_i16_1(<3 x i64> %x) { 137; LE-LABEL: @shrinkExtractElt_i64_to_i16_1( 138; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 139; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 4 140; LE-NEXT: ret i16 [[T]] 141; 142; BE-LABEL: @shrinkExtractElt_i64_to_i16_1( 143; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 144; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 7 145; BE-NEXT: ret i16 [[T]] 146; 147 %e = extractelement <3 x i64> %x, i16 1 148 %t = trunc i64 %e to i16 149 ret i16 %t 150} 151 152define i16 @shrinkExtractElt_i64_to_i16_2(<3 x i64> %x) { 153; LE-LABEL: @shrinkExtractElt_i64_to_i16_2( 154; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 155; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 8 156; LE-NEXT: ret i16 [[T]] 157; 158; BE-LABEL: @shrinkExtractElt_i64_to_i16_2( 159; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16> 160; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 11 161; BE-NEXT: ret i16 [[T]] 162; 163 %e = extractelement <3 x i64> %x, i16 2 164 %t = trunc i64 %e to i16 165 ret i16 %t 166} 167 168; Crazy types may be ok. 169define i11 @shrinkExtractElt_i33_to_11_2(<3 x i33> %x) { 170; LE-LABEL: @shrinkExtractElt_i33_to_11_2( 171; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i33> [[X:%.*]] to <9 x i11> 172; LE-NEXT: [[T:%.*]] = extractelement <9 x i11> [[TMP1]], i64 6 173; LE-NEXT: ret i11 [[T]] 174; 175; BE-LABEL: @shrinkExtractElt_i33_to_11_2( 176; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i33> [[X:%.*]] to <9 x i11> 177; BE-NEXT: [[T:%.*]] = extractelement <9 x i11> [[TMP1]], i64 8 178; BE-NEXT: ret i11 [[T]] 179; 180 %e = extractelement <3 x i33> %x, i16 2 181 %t = trunc i33 %e to i11 182 ret i11 %t 183} 184 185; Do not optimize if it would result in an invalid bitcast instruction. 186define i13 @shrinkExtractElt_i67_to_i13_2(<3 x i67> %x) { 187; ANY-LABEL: @shrinkExtractElt_i67_to_i13_2( 188; ANY-NEXT: [[E:%.*]] = extractelement <3 x i67> [[X:%.*]], i64 2 189; ANY-NEXT: [[T:%.*]] = trunc i67 [[E]] to i13 190; ANY-NEXT: ret i13 [[T]] 191; 192 %e = extractelement <3 x i67> %x, i459 2 193 %t = trunc i67 %e to i13 194 ret i13 %t 195} 196 197; Do not optimize if the bitcast instruction would be valid, but the 198; transform would be wrong. 199define i30 @shrinkExtractElt_i40_to_i30_1(<3 x i40> %x) { 200; ANY-LABEL: @shrinkExtractElt_i40_to_i30_1( 201; ANY-NEXT: [[E:%.*]] = extractelement <3 x i40> [[X:%.*]], i64 1 202; ANY-NEXT: [[T:%.*]] = trunc i40 [[E]] to i30 203; ANY-NEXT: ret i30 [[T]] 204; 205 %e = extractelement <3 x i40> %x, i32 1 206 %t = trunc i40 %e to i30 207 ret i30 %t 208} 209 210; Do not optimize if the shift amount isn't a whole number of truncated bits. 211define i16 @shrinkShiftExtractElt_i64_to_i16_0_badshift(<3 x i64> %x) { 212; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_0_badshift( 213; ANY-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 0 214; ANY-NEXT: [[S:%.*]] = lshr i64 [[E]], 31 215; ANY-NEXT: [[T:%.*]] = trunc i64 [[S]] to i16 216; ANY-NEXT: ret i16 [[T]] 217; 218 %e = extractelement <3 x i64> %x, i16 0 219 %s = lshr i64 %e, 31 220 %t = trunc i64 %s to i16 221 ret i16 %t 222} 223 224; Do not canonicalize if that would increase the instruction count. 225declare void @use(i64) 226define i16 @shrinkExtractElt_i64_to_i16_2_extra_use(<3 x i64> %x) { 227; ANY-LABEL: @shrinkExtractElt_i64_to_i16_2_extra_use( 228; ANY-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2 229; ANY-NEXT: call void @use(i64 [[E]]) 230; ANY-NEXT: [[T:%.*]] = trunc i64 [[E]] to i16 231; ANY-NEXT: ret i16 [[T]] 232; 233 %e = extractelement <3 x i64> %x, i64 2 234 call void @use(i64 %e) 235 %t = trunc i64 %e to i16 236 ret i16 %t 237} 238 239; Do not canonicalize if that would increase the instruction count. 240define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use(<3 x i64> %x) { 241; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use( 242; ANY-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2 243; ANY-NEXT: [[S:%.*]] = lshr i64 [[E]], 48 244; ANY-NEXT: call void @use(i64 [[S]]) 245; ANY-NEXT: [[T:%.*]] = trunc nuw i64 [[S]] to i16 246; ANY-NEXT: ret i16 [[T]] 247; 248 %e = extractelement <3 x i64> %x, i64 2 249 %s = lshr i64 %e, 48 250 call void @use(i64 %s) 251 %t = trunc i64 %s to i16 252 ret i16 %t 253} 254 255; OK to reuse the extract if we remove the shift+trunc. 256define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(<3 x i64> %x) { 257; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use( 258; LE-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2 259; LE-NEXT: call void @use(i64 [[E]]) 260; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16> 261; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 11 262; LE-NEXT: ret i16 [[T]] 263; 264; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use( 265; BE-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2 266; BE-NEXT: call void @use(i64 [[E]]) 267; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16> 268; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 8 269; BE-NEXT: ret i16 [[T]] 270; 271 %e = extractelement <3 x i64> %x, i64 2 272 call void @use(i64 %e) 273 %s = lshr i64 %e, 48 274 %t = trunc i64 %s to i16 275 ret i16 %t 276} 277 278; Check to ensure PR45314 remains fixed. 279define <4 x i64> @PR45314(<4 x i64> %x) { 280; LE-LABEL: @PR45314( 281; LE-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> [[X:%.*]] to <8 x i32> 282; LE-NEXT: [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> zeroinitializer 283; LE-NEXT: [[B:%.*]] = bitcast <8 x i32> [[S]] to <4 x i64> 284; LE-NEXT: ret <4 x i64> [[B]] 285; 286; BE-LABEL: @PR45314( 287; BE-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> [[X:%.*]] to <8 x i32> 288; BE-NEXT: [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 289; BE-NEXT: [[B:%.*]] = bitcast <8 x i32> [[S]] to <4 x i64> 290; BE-NEXT: ret <4 x i64> [[B]] 291; 292 %e = extractelement <4 x i64> %x, i32 0 293 %t = trunc i64 %e to i32 294 %i = insertelement <8 x i32> poison, i32 %t, i32 0 295 %s = shufflevector <8 x i32> %i, <8 x i32> poison, <8 x i32> zeroinitializer 296 %b = bitcast <8 x i32> %s to <4 x i64> 297 ret <4 x i64> %b 298} 299