1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; llvm.experimental.vector.insert canonicalizes to shufflevector in the fixed case. In the 5; scalable case, we lower to the INSERT_SUBVECTOR ISD node. 6 7declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 %idx) 8declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 %idx) 9declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 %idx) 10declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v8i32(<8 x i32> %vec, <8 x i32> %subvec, i64 %idx) 11declare <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> %vec, <4 x i32> %subvec, i64 %idx) 12 13; ============================================================================ ; 14; Trivial cases 15; ============================================================================ ; 16 17; An insert that entirely overwrites an <n x ty> with another <n x ty> is a 18; nop. 19define <8 x i32> @trivial_nop(<8 x i32> %vec, <8 x i32> %subvec) { 20; CHECK-LABEL: @trivial_nop( 21; CHECK-NEXT: ret <8 x i32> [[SUBVEC:%.*]] 22; 23 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v8i32(<8 x i32> %vec, <8 x i32> %subvec, i64 0) 24 ret <8 x i32> %1 25} 26 27; ============================================================================ ; 28; Valid canonicalizations 29; ============================================================================ ; 30 31define <8 x i32> @valid_insertion_a(<8 x i32> %vec, <2 x i32> %subvec) { 32; CHECK-LABEL: @valid_insertion_a( 33; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 34; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 35; CHECK-NEXT: ret <8 x i32> [[TMP2]] 36; 37 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 0) 38 ret <8 x i32> %1 39} 40 41define <8 x i32> @valid_insertion_b(<8 x i32> %vec, <2 x i32> %subvec) { 42; CHECK-LABEL: @valid_insertion_b( 43; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 44; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 4, i32 5, i32 6, i32 7> 45; CHECK-NEXT: ret <8 x i32> [[TMP2]] 46; 47 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 2) 48 ret <8 x i32> %1 49} 50 51define <8 x i32> @valid_insertion_c(<8 x i32> %vec, <2 x i32> %subvec) { 52; CHECK-LABEL: @valid_insertion_c( 53; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 54; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 6, i32 7> 55; CHECK-NEXT: ret <8 x i32> [[TMP2]] 56; 57 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 4) 58 ret <8 x i32> %1 59} 60 61define <8 x i32> @valid_insertion_d(<8 x i32> %vec, <2 x i32> %subvec) { 62; CHECK-LABEL: @valid_insertion_d( 63; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 64; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 8, i32 9> 65; CHECK-NEXT: ret <8 x i32> [[TMP2]] 66; 67 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 6) 68 ret <8 x i32> %1 69} 70 71define <8 x i32> @valid_insertion_e(<8 x i32> %vec, <4 x i32> %subvec) { 72; CHECK-LABEL: @valid_insertion_e( 73; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[SUBVEC:%.*]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> 74; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15> 75; CHECK-NEXT: ret <8 x i32> [[TMP2]] 76; 77 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 0) 78 ret <8 x i32> %1 79} 80 81define <8 x i32> @valid_insertion_f(<8 x i32> %vec, <4 x i32> %subvec) { 82; CHECK-LABEL: @valid_insertion_f( 83; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[SUBVEC:%.*]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> 84; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> 85; CHECK-NEXT: ret <8 x i32> [[TMP2]] 86; 87 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 4) 88 ret <8 x i32> %1 89} 90 91define <8 x i32> @valid_insertion_g(<8 x i32> %vec, <3 x i32> %subvec) { 92; CHECK-LABEL: @valid_insertion_g( 93; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x i32> [[SUBVEC:%.*]], <3 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 94; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 11, i32 12, i32 13, i32 14, i32 15> 95; CHECK-NEXT: ret <8 x i32> [[TMP2]] 96; 97 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 0) 98 ret <8 x i32> %1 99} 100 101define <8 x i32> @valid_insertion_h(<8 x i32> %vec, <3 x i32> %subvec) { 102; CHECK-LABEL: @valid_insertion_h( 103; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x i32> [[SUBVEC:%.*]], <3 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 104; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 9, i32 10, i32 6, i32 7> 105; CHECK-NEXT: ret <8 x i32> [[TMP2]] 106; 107 %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 3) 108 ret <8 x i32> %1 109} 110 111; ============================================================================ ; 112; Scalable cases 113; ============================================================================ ; 114 115; Scalable insertions should not be canonicalized. This will be lowered to the 116; INSERT_SUBVECTOR ISD node later. 117define <vscale x 4 x i32> @scalable_insert(<vscale x 4 x i32> %vec, <4 x i32> %subvec) { 118; CHECK-LABEL: @scalable_insert( 119; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> [[VEC:%.*]], <4 x i32> [[SUBVEC:%.*]], i64 0) 120; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]] 121; 122 %1 = call <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> %vec, <4 x i32> %subvec, i64 0) 123 ret <vscale x 4 x i32> %1 124} 125