1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i32 @extractelement_in_range(<vscale x 4 x i32> %a) { 5; CHECK-LABEL: @extractelement_in_range( 6; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x i32> [[A:%.*]], i64 1 7; CHECK-NEXT: ret i32 [[R]] 8; 9 %r = extractelement <vscale x 4 x i32> %a, i64 1 10 ret i32 %r 11} 12 13define i32 @extractelement_maybe_out_of_range(<vscale x 4 x i32> %a) { 14; CHECK-LABEL: @extractelement_maybe_out_of_range( 15; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x i32> [[A:%.*]], i64 4 16; CHECK-NEXT: ret i32 [[R]] 17; 18 %r = extractelement <vscale x 4 x i32> %a, i64 4 19 ret i32 %r 20} 21 22define i32 @extractelement_bitcast(float %f) { 23; CHECK-LABEL: @extractelement_bitcast( 24; CHECK-NEXT: [[R:%.*]] = bitcast float [[F:%.*]] to i32 25; CHECK-NEXT: ret i32 [[R]] 26; 27 %vec_float = insertelement <vscale x 4 x float> undef, float %f, i32 0 28 %vec_int = bitcast <vscale x 4 x float> %vec_float to <vscale x 4 x i32> 29 %r = extractelement <vscale x 4 x i32> %vec_int, i32 0 30 ret i32 %r 31} 32 33define i8 @extractelement_bitcast_to_trunc(<vscale x 2 x i32> %a, i32 %x) { 34; CHECK-LABEL: @extractelement_bitcast_to_trunc( 35; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i8 36; CHECK-NEXT: ret i8 [[R]] 37; 38 %vec = insertelement <vscale x 2 x i32> %a, i32 %x, i32 1 39 %vec_cast = bitcast <vscale x 2 x i32> %vec to <vscale x 8 x i8> 40 %r = extractelement <vscale x 8 x i8> %vec_cast, i32 4 41 ret i8 %r 42} 43 44define i8 @extractelement_bitcast_useless_insert(<vscale x 2 x i32> %a, i32 %x) { 45; CHECK-LABEL: @extractelement_bitcast_useless_insert( 46; CHECK-NEXT: [[TMP1:%.*]] = bitcast <vscale x 2 x i32> [[A:%.*]] to <vscale x 8 x i8> 47; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 8 x i8> [[TMP1]], i64 2 48; CHECK-NEXT: ret i8 [[R]] 49; 50 %vec = insertelement <vscale x 2 x i32> %a, i32 %x, i32 1 ; <- This insert could be removed. 51 %vec_cast = bitcast <vscale x 2 x i32> %vec to <vscale x 8 x i8> 52 %r = extractelement <vscale x 8 x i8> %vec_cast, i32 2 53 ret i8 %r 54} 55 56define i32 @extractelement_shuffle_maybe_out_of_range(i32 %v) { 57; CHECK-LABEL: @extractelement_shuffle_maybe_out_of_range( 58; CHECK-NEXT: [[IN:%.*]] = insertelement <vscale x 4 x i32> undef, i32 [[V:%.*]], i64 0 59; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[IN]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer 60; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x i32> [[SPLAT]], i64 4 61; CHECK-NEXT: ret i32 [[R]] 62; 63 %in = insertelement <vscale x 4 x i32> undef, i32 %v, i32 0 64 %splat = shufflevector <vscale x 4 x i32> %in, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer 65 %r = extractelement <vscale x 4 x i32> %splat, i32 4 66 ret i32 %r 67} 68 69define i32 @extractelement_shuffle_invalid_index(i32 %v) { 70; CHECK-LABEL: @extractelement_shuffle_invalid_index( 71; CHECK-NEXT: [[IN:%.*]] = insertelement <vscale x 4 x i32> undef, i32 [[V:%.*]], i64 0 72; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[IN]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer 73; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x i32> [[SPLAT]], i64 4294967295 74; CHECK-NEXT: ret i32 [[R]] 75; 76 %in = insertelement <vscale x 4 x i32> undef, i32 %v, i32 0 77 %splat = shufflevector <vscale x 4 x i32> %in, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer 78 %r = extractelement <vscale x 4 x i32> %splat, i32 -1 79 ret i32 %r 80} 81 82define <vscale x 4 x i32> @extractelement_insertelement_same_positions(<vscale x 4 x i32> %vec) { 83; CHECK-LABEL: @extractelement_insertelement_same_positions( 84; CHECK-NEXT: ret <vscale x 4 x i32> [[VEC:%.*]] 85; 86 %vec.e0 = extractelement <vscale x 4 x i32> %vec, i32 0 87 %vec.e1 = extractelement <vscale x 4 x i32> %vec, i32 1 88 %vec.e2 = extractelement <vscale x 4 x i32> %vec, i32 2 89 %vec.e3 = extractelement <vscale x 4 x i32> %vec, i32 3 90 %1 = insertelement <vscale x 4 x i32> %vec, i32 %vec.e0, i32 0 91 %2 = insertelement <vscale x 4 x i32> %1, i32 %vec.e1, i32 1 92 %3 = insertelement <vscale x 4 x i32> %2, i32 %vec.e2, i32 2 93 %4 = insertelement <vscale x 4 x i32> %3, i32 %vec.e3, i32 3 94 ret <vscale x 4 x i32> %4 95} 96 97define <vscale x 4 x i32> @extractelement_insertelement_diff_positions(<vscale x 4 x i32> %vec) { 98; CHECK-LABEL: @extractelement_insertelement_diff_positions( 99; CHECK-NEXT: [[VEC_E0:%.*]] = extractelement <vscale x 4 x i32> [[VEC:%.*]], i64 4 100; CHECK-NEXT: [[VEC_E1:%.*]] = extractelement <vscale x 4 x i32> [[VEC]], i64 5 101; CHECK-NEXT: [[VEC_E2:%.*]] = extractelement <vscale x 4 x i32> [[VEC]], i64 6 102; CHECK-NEXT: [[VEC_E3:%.*]] = extractelement <vscale x 4 x i32> [[VEC]], i64 7 103; CHECK-NEXT: [[TMP1:%.*]] = insertelement <vscale x 4 x i32> [[VEC]], i32 [[VEC_E0]], i64 0 104; CHECK-NEXT: [[TMP2:%.*]] = insertelement <vscale x 4 x i32> [[TMP1]], i32 [[VEC_E1]], i64 1 105; CHECK-NEXT: [[TMP3:%.*]] = insertelement <vscale x 4 x i32> [[TMP2]], i32 [[VEC_E2]], i64 2 106; CHECK-NEXT: [[TMP4:%.*]] = insertelement <vscale x 4 x i32> [[TMP3]], i32 [[VEC_E3]], i64 3 107; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP4]] 108; 109 %vec.e0 = extractelement <vscale x 4 x i32> %vec, i32 4 110 %vec.e1 = extractelement <vscale x 4 x i32> %vec, i32 5 111 %vec.e2 = extractelement <vscale x 4 x i32> %vec, i32 6 112 %vec.e3 = extractelement <vscale x 4 x i32> %vec, i32 7 113 %1 = insertelement <vscale x 4 x i32> %vec, i32 %vec.e0, i32 0 114 %2 = insertelement <vscale x 4 x i32> %1, i32 %vec.e1, i32 1 115 %3 = insertelement <vscale x 4 x i32> %2, i32 %vec.e2, i32 2 116 %4 = insertelement <vscale x 4 x i32> %3, i32 %vec.e3, i32 3 117 ret <vscale x 4 x i32> %4 118} 119 120define i32 @bitcast_of_extractelement( <vscale x 2 x float> %d) { 121; CHECK-LABEL: @bitcast_of_extractelement( 122; CHECK-NEXT: [[BC:%.*]] = bitcast <vscale x 2 x float> [[D:%.*]] to <vscale x 2 x i32> 123; CHECK-NEXT: [[CAST:%.*]] = extractelement <vscale x 2 x i32> [[BC]], i64 0 124; CHECK-NEXT: ret i32 [[CAST]] 125; 126 %ext = extractelement <vscale x 2 x float> %d, i32 0 127 %cast = bitcast float %ext to i32 128 ret i32 %cast 129} 130 131define i1 @extractelement_is_zero(<vscale x 2 x i32> %d, i1 %b, i32 %z) { 132; CHECK-LABEL: @extractelement_is_zero( 133; CHECK-NEXT: [[EXT:%.*]] = extractelement <vscale x 2 x i32> [[D:%.*]], i64 0 134; CHECK-NEXT: [[BB:%.*]] = icmp eq i32 [[EXT]], 0 135; CHECK-NEXT: ret i1 [[BB]] 136; 137 %ext = extractelement <vscale x 2 x i32> %d, i32 0 138 %bb = icmp eq i32 %ext, 0 139 ret i1 %bb 140} 141 142; OSS-Fuzz #25272 143; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25272 144define i32 @ossfuzz_25272(float %f) { 145; CHECK-LABEL: @ossfuzz_25272( 146; CHECK-NEXT: [[VEC_FLOAT:%.*]] = insertelement <vscale x 4 x float> undef, float [[F:%.*]], i64 0 147; CHECK-NEXT: [[VEC_INT:%.*]] = bitcast <vscale x 4 x float> [[VEC_FLOAT]] to <vscale x 4 x i32> 148; CHECK-NEXT: [[E:%.*]] = extractelement <vscale x 4 x i32> [[VEC_INT]], i64 2147483647 149; CHECK-NEXT: ret i32 [[E]] 150; 151 %vec_float = insertelement <vscale x 4 x float> undef, float %f, i32 0 152 %vec_int = bitcast <vscale x 4 x float> %vec_float to <vscale x 4 x i32> 153 %E = extractelement <vscale x 4 x i32> %vec_int, i32 2147483647 154 ret i32 %E 155} 156 157; Step vector optimization 158 159define i64 @ext_lane0_from_stepvec() { 160; CHECK-LABEL: @ext_lane0_from_stepvec( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: ret i64 0 163; 164entry: 165 %0 = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 166 %1 = extractelement <vscale x 4 x i64> %0, i32 0 167 ret i64 %1 168} 169 170define i32 @ext_lane3_from_stepvec() { 171; CHECK-LABEL: @ext_lane3_from_stepvec( 172; CHECK-NEXT: entry: 173; CHECK-NEXT: ret i32 3 174; 175entry: 176 %0 = call <vscale x 4 x i32> @llvm.stepvector.nxv4i32() 177 %1 = extractelement <vscale x 4 x i32> %0, i64 3 178 ret i32 %1 179} 180 181define i64 @ext_lane_out_of_range_from_stepvec() { 182; CHECK-LABEL: @ext_lane_out_of_range_from_stepvec( 183; CHECK-NEXT: entry: 184; CHECK-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 185; CHECK-NEXT: [[TMP1:%.*]] = extractelement <vscale x 4 x i64> [[TMP0]], i64 4 186; CHECK-NEXT: ret i64 [[TMP1]] 187; 188entry: 189 %0 = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 190 %1 = extractelement <vscale x 4 x i64> %0, i32 4 191 ret i64 %1 192} 193 194define i64 @ext_lane_invalid_from_stepvec() { 195; CHECK-LABEL: @ext_lane_invalid_from_stepvec( 196; CHECK-NEXT: entry: 197; CHECK-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 198; CHECK-NEXT: [[TMP1:%.*]] = extractelement <vscale x 4 x i64> [[TMP0]], i64 4294967295 199; CHECK-NEXT: ret i64 [[TMP1]] 200; 201entry: 202 %0 = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 203 %1 = extractelement <vscale x 4 x i64> %0, i32 -1 204 ret i64 %1 205} 206 207define i64 @ext_lane_unknown_from_stepvec(i32 %v) { 208; CHECK-LABEL: @ext_lane_unknown_from_stepvec( 209; CHECK-NEXT: entry: 210; CHECK-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 211; CHECK-NEXT: [[TMP1:%.*]] = extractelement <vscale x 4 x i64> [[TMP0]], i32 [[V:%.*]] 212; CHECK-NEXT: ret i64 [[TMP1]] 213; 214entry: 215 %0 = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 216 %1 = extractelement <vscale x 4 x i64> %0, i32 %v 217 ret i64 %1 218} 219 220; Check that poison is returned when the extracted element has wrapped. 221 222define i8 @ext_lane256_from_stepvec() { 223; CHECK-LABEL: @ext_lane256_from_stepvec( 224; CHECK-NEXT: entry: 225; CHECK-NEXT: ret i8 poison 226; 227entry: 228 %0 = call <vscale x 512 x i8> @llvm.stepvector.nxv512i8() 229 %1 = extractelement <vscale x 512 x i8> %0, i64 256 230 ret i8 %1 231} 232 233define i8 @ext_lane255_from_stepvec() { 234; CHECK-LABEL: @ext_lane255_from_stepvec( 235; CHECK-NEXT: entry: 236; CHECK-NEXT: ret i8 -1 237; 238entry: 239 %0 = call <vscale x 512 x i8> @llvm.stepvector.nxv512i8() 240 %1 = extractelement <vscale x 512 x i8> %0, i64 255 241 ret i8 %1 242} 243 244; Check that we can extract more complex cases where the stepvector is 245; involved in a binary operation prior to the lane being extracted. 246 247define i64 @ext_lane0_from_add_with_stepvec(i64 %i) { 248; CHECK-LABEL: @ext_lane0_from_add_with_stepvec( 249; CHECK-NEXT: ret i64 [[I:%.*]] 250; 251 %tmp = insertelement <vscale x 2 x i64> poison, i64 %i, i32 0 252 %splatofi = shufflevector <vscale x 2 x i64> %tmp, <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer 253 %stepvec = call <vscale x 2 x i64> @llvm.stepvector.nxv2i64() 254 %add = add <vscale x 2 x i64> %splatofi, %stepvec 255 %res = extractelement <vscale x 2 x i64> %add, i32 0 256 ret i64 %res 257} 258 259define i1 @ext_lane1_from_cmp_with_stepvec(i64 %i) { 260; CHECK-LABEL: @ext_lane1_from_cmp_with_stepvec( 261; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[I:%.*]], 1 262; CHECK-NEXT: ret i1 [[RES]] 263; 264 %tmp = insertelement <vscale x 2 x i64> poison, i64 %i, i32 0 265 %splatofi = shufflevector <vscale x 2 x i64> %tmp, <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer 266 %stepvec = call <vscale x 2 x i64> @llvm.stepvector.nxv2i64() 267 %cmp = icmp eq <vscale x 2 x i64> %splatofi, %stepvec 268 %res = extractelement <vscale x 2 x i1> %cmp, i32 1 269 ret i1 %res 270} 271 272define ptr @ext_lane_from_bitcast_of_splat(ptr %v) { 273; CHECK-LABEL: @ext_lane_from_bitcast_of_splat( 274; CHECK-NEXT: entry: 275; CHECK-NEXT: ret ptr [[V:%.*]] 276; 277entry: 278 %in = insertelement <vscale x 4 x ptr> poison, ptr %v, i32 0 279 %splat = shufflevector <vscale x 4 x ptr> %in, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer 280 %bc = bitcast <vscale x 4 x ptr> %splat to <vscale x 4 x ptr> 281 %r = extractelement <vscale x 4 x ptr> %bc, i32 3 282 ret ptr %r 283} 284 285declare <vscale x 2 x i64> @llvm.stepvector.nxv2i64() 286declare <vscale x 4 x i64> @llvm.stepvector.nxv4i64() 287declare <vscale x 4 x i32> @llvm.stepvector.nxv4i32() 288declare <vscale x 512 x i8> @llvm.stepvector.nxv512i8() 289