1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S -data-layout="E-n64" | FileCheck %s --check-prefixes=ALL,BE 3; RUN: opt < %s -passes=instcombine -S -data-layout="e-n64" | FileCheck %s --check-prefixes=ALL,LE 4 5declare void @use(<2 x i8>) 6 7; i16 is a common type, so we can convert independently of the data layout. 8; Endian determines if a shift is needed (and so the transform is avoided). 9 10define i16 @insert0_v2i8(i16 %x, i8 %y) { 11; BE-LABEL: @insert0_v2i8( 12; BE-NEXT: [[V:%.*]] = bitcast i16 [[X:%.*]] to <2 x i8> 13; BE-NEXT: [[I:%.*]] = insertelement <2 x i8> [[V]], i8 [[Y:%.*]], i64 0 14; BE-NEXT: [[R:%.*]] = bitcast <2 x i8> [[I]] to i16 15; BE-NEXT: ret i16 [[R]] 16; 17; LE-LABEL: @insert0_v2i8( 18; LE-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -256 19; LE-NEXT: [[TMP2:%.*]] = zext i8 [[Y:%.*]] to i16 20; LE-NEXT: [[R:%.*]] = or disjoint i16 [[TMP1]], [[TMP2]] 21; LE-NEXT: ret i16 [[R]] 22; 23 %v = bitcast i16 %x to <2 x i8> 24 %i = insertelement <2 x i8> %v, i8 %y, i8 0 25 %r = bitcast <2 x i8> %i to i16 26 ret i16 %r 27} 28 29; i16 is a common type, so we can convert independently of the data layout. 30; Endian determines if a shift is needed (and so the transform is avoided). 31 32define i16 @insert1_v2i8(i16 %x, i8 %y) { 33; BE-LABEL: @insert1_v2i8( 34; BE-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -256 35; BE-NEXT: [[TMP2:%.*]] = zext i8 [[Y:%.*]] to i16 36; BE-NEXT: [[R:%.*]] = or disjoint i16 [[TMP1]], [[TMP2]] 37; BE-NEXT: ret i16 [[R]] 38; 39; LE-LABEL: @insert1_v2i8( 40; LE-NEXT: [[V:%.*]] = bitcast i16 [[X:%.*]] to <2 x i8> 41; LE-NEXT: [[I:%.*]] = insertelement <2 x i8> [[V]], i8 [[Y:%.*]], i64 1 42; LE-NEXT: [[R:%.*]] = bitcast <2 x i8> [[I]] to i16 43; LE-NEXT: ret i16 [[R]] 44; 45 %v = bitcast i16 %x to <2 x i8> 46 %i = insertelement <2 x i8> %v, i8 %y, i8 1 47 %r = bitcast <2 x i8> %i to i16 48 ret i16 %r 49} 50 51; i32 is a common type, so we can convert independently of the data layout. 52; Endian determines if a shift is needed (and so the transform is avoided). 53 54define i32 @insert0_v4i8(i32 %x, i8 %y) { 55; BE-LABEL: @insert0_v4i8( 56; BE-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <4 x i8> 57; BE-NEXT: [[I:%.*]] = insertelement <4 x i8> [[V]], i8 [[Y:%.*]], i64 0 58; BE-NEXT: [[R:%.*]] = bitcast <4 x i8> [[I]] to i32 59; BE-NEXT: ret i32 [[R]] 60; 61; LE-LABEL: @insert0_v4i8( 62; LE-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -256 63; LE-NEXT: [[TMP2:%.*]] = zext i8 [[Y:%.*]] to i32 64; LE-NEXT: [[R:%.*]] = or disjoint i32 [[TMP1]], [[TMP2]] 65; LE-NEXT: ret i32 [[R]] 66; 67 %v = bitcast i32 %x to <4 x i8> 68 %i = insertelement <4 x i8> %v, i8 %y, i8 0 69 %r = bitcast <4 x i8> %i to i32 70 ret i32 %r 71} 72 73; i32 is a common type, so we can convert independently of the data layout. 74; Endian determines if a shift is needed (and so the transform is avoided). 75; half type can not be used in zext instruction (and so the transform is avoided). 76 77define i32 @insert0_v2half(i32 %x, half %y) { 78; ALL-LABEL: @insert0_v2half( 79; ALL-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x half> 80; ALL-NEXT: [[I:%.*]] = insertelement <2 x half> [[V]], half [[Y:%.*]], i64 0 81; ALL-NEXT: [[R:%.*]] = bitcast <2 x half> [[I]] to i32 82; ALL-NEXT: ret i32 [[R]] 83; 84 %v = bitcast i32 %x to <2 x half> 85 %i = insertelement <2 x half> %v, half %y, i8 0 86 %r = bitcast <2 x half> %i to i32 87 ret i32 %r 88} 89 90; i64 is a legal type, so we can convert based on the data layout. 91; Endian determines if a shift is needed (and so the transform is avoided). 92 93define i64 @insert0_v4i16(i64 %x, i16 %y) { 94; BE-LABEL: @insert0_v4i16( 95; BE-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <4 x i16> 96; BE-NEXT: [[I:%.*]] = insertelement <4 x i16> [[V]], i16 [[Y:%.*]], i64 0 97; BE-NEXT: [[R:%.*]] = bitcast <4 x i16> [[I]] to i64 98; BE-NEXT: ret i64 [[R]] 99; 100; LE-LABEL: @insert0_v4i16( 101; LE-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], -65536 102; LE-NEXT: [[TMP2:%.*]] = zext i16 [[Y:%.*]] to i64 103; LE-NEXT: [[R:%.*]] = or disjoint i64 [[TMP1]], [[TMP2]] 104; LE-NEXT: ret i64 [[R]] 105; 106 %v = bitcast i64 %x to <4 x i16> 107 %i = insertelement <4 x i16> %v, i16 %y, i8 0 108 %r = bitcast <4 x i16> %i to i64 109 ret i64 %r 110} 111 112; Negative test - shifts needed for both endians. 113 114define i64 @insert1_v4i16(i64 %x, i16 %y) { 115; ALL-LABEL: @insert1_v4i16( 116; ALL-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <4 x i16> 117; ALL-NEXT: [[I:%.*]] = insertelement <4 x i16> [[V]], i16 [[Y:%.*]], i64 1 118; ALL-NEXT: [[R:%.*]] = bitcast <4 x i16> [[I]] to i64 119; ALL-NEXT: ret i64 [[R]] 120; 121 %v = bitcast i64 %x to <4 x i16> 122 %i = insertelement <4 x i16> %v, i16 %y, i8 1 123 %r = bitcast <4 x i16> %i to i64 124 ret i64 %r 125} 126 127; i64 is a legal type, so we can convert based on the data layout. 128; Endian determines if a shift is needed (and so the transform is avoided). 129 130define i64 @insert3_v4i16(i64 %x, i16 %y) { 131; BE-LABEL: @insert3_v4i16( 132; BE-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], -65536 133; BE-NEXT: [[TMP2:%.*]] = zext i16 [[Y:%.*]] to i64 134; BE-NEXT: [[R:%.*]] = or disjoint i64 [[TMP1]], [[TMP2]] 135; BE-NEXT: ret i64 [[R]] 136; 137; LE-LABEL: @insert3_v4i16( 138; LE-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <4 x i16> 139; LE-NEXT: [[I:%.*]] = insertelement <4 x i16> [[V]], i16 [[Y:%.*]], i64 3 140; LE-NEXT: [[R:%.*]] = bitcast <4 x i16> [[I]] to i64 141; LE-NEXT: ret i64 [[R]] 142; 143 %v = bitcast i64 %x to <4 x i16> 144 %i = insertelement <4 x i16> %v, i16 %y, i8 3 145 %r = bitcast <4 x i16> %i to i64 146 ret i64 %r 147} 148 149; Negative test - i128 is not a legal type, so we do not convert based on the data layout. 150 151define i128 @insert0_v4i32(i128 %x, i32 %y) { 152; ALL-LABEL: @insert0_v4i32( 153; ALL-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <4 x i32> 154; ALL-NEXT: [[I:%.*]] = insertelement <4 x i32> [[V]], i32 [[Y:%.*]], i64 0 155; ALL-NEXT: [[R:%.*]] = bitcast <4 x i32> [[I]] to i128 156; ALL-NEXT: ret i128 [[R]] 157; 158 %v = bitcast i128 %x to <4 x i32> 159 %i = insertelement <4 x i32> %v, i32 %y, i8 0 160 %r = bitcast <4 x i32> %i to i128 161 ret i128 %r 162} 163 164; Negative test - extra use requires more instructions. 165 166define i16 @insert0_v2i8_use1(i16 %x, i8 %y) { 167; ALL-LABEL: @insert0_v2i8_use1( 168; ALL-NEXT: [[V:%.*]] = bitcast i16 [[X:%.*]] to <2 x i8> 169; ALL-NEXT: call void @use(<2 x i8> [[V]]) 170; ALL-NEXT: [[I:%.*]] = insertelement <2 x i8> [[V]], i8 [[Y:%.*]], i64 0 171; ALL-NEXT: [[R:%.*]] = bitcast <2 x i8> [[I]] to i16 172; ALL-NEXT: ret i16 [[R]] 173; 174 %v = bitcast i16 %x to <2 x i8> 175 call void @use(<2 x i8> %v) 176 %i = insertelement <2 x i8> %v, i8 %y, i8 0 177 %r = bitcast <2 x i8> %i to i16 178 ret i16 %r 179} 180 181; Negative test - extra use requires more instructions. 182 183define i16 @insert0_v2i8_use2(i16 %x, i8 %y) { 184; ALL-LABEL: @insert0_v2i8_use2( 185; ALL-NEXT: [[V:%.*]] = bitcast i16 [[X:%.*]] to <2 x i8> 186; ALL-NEXT: [[I:%.*]] = insertelement <2 x i8> [[V]], i8 [[Y:%.*]], i64 0 187; ALL-NEXT: call void @use(<2 x i8> [[I]]) 188; ALL-NEXT: [[R:%.*]] = bitcast <2 x i8> [[I]] to i16 189; ALL-NEXT: ret i16 [[R]] 190; 191 %v = bitcast i16 %x to <2 x i8> 192 %i = insertelement <2 x i8> %v, i8 %y, i8 0 193 call void @use(<2 x i8> %i) 194 %r = bitcast <2 x i8> %i to i16 195 ret i16 %r 196} 197