1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=CHECK --check-prefix=AVX 3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=CHECK --check-prefix=AVX2 4 5 ; Check constant loads of every 128-bit and 256-bit vector type 6 ; for size optimization using splat ops available with AVX and AVX2. 7 8 ; There is no AVX broadcast from double to 128-bit vector because movddup has been around since SSE3 (grrr). 9 define <2 x double> @splat_v2f64(<2 x double> %x) #0 { 10 ; CHECK-LABEL: splat_v2f64: 11 ; CHECK: # BB#0: 12 ; CHECK-NEXT: vmovddup {{.*#+}} xmm1 = mem[0,0] 13 ; CHECK-NEXT: vaddpd %xmm1, %xmm0, %xmm0 14 ; CHECK-NEXT: retq 15 %add = fadd <2 x double> %x, <double 1.0, double 1.0> 16 ret <2 x double> %add 17 } 18 19 define <4 x double> @splat_v4f64(<4 x double> %x) #1 { 20 ; CHECK-LABEL: splat_v4f64: 21 ; CHECK: # BB#0: 22 ; CHECK-NEXT: vbroadcastsd {{.*}}(%rip), %ymm1 23 ; CHECK-NEXT: vaddpd %ymm1, %ymm0, %ymm0 24 ; CHECK-NEXT: retq 25 %add = fadd <4 x double> %x, <double 1.0, double 1.0, double 1.0, double 1.0> 26 ret <4 x double> %add 27 } 28 29 define <4 x float> @splat_v4f32(<4 x float> %x) #0 { 30 ; CHECK-LABEL: splat_v4f32: 31 ; CHECK: # BB#0: 32 ; CHECK-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 33 ; CHECK-NEXT: vaddps %xmm1, %xmm0, %xmm0 34 ; CHECK-NEXT: retq 35 %add = fadd <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 36 ret <4 x float> %add 37 } 38 39 define <8 x float> @splat_v8f32(<8 x float> %x) #1 { 40 ; CHECK-LABEL: splat_v8f32: 41 ; CHECK: # BB#0: 42 ; CHECK-NEXT: vbroadcastss {{.*}}(%rip), %ymm1 43 ; CHECK-NEXT: vaddps %ymm1, %ymm0, %ymm0 44 ; CHECK-NEXT: retq 45 %add = fadd <8 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0> 46 ret <8 x float> %add 47 } 48 49 ; AVX can't do integer splats, so fake it: use vmovddup to splat 64-bit value. 50 ; We also generate vmovddup for AVX2 because it's one byte smaller than vpbroadcastq. 51 define <2 x i64> @splat_v2i64(<2 x i64> %x) #1 { 52 ; CHECK-LABEL: splat_v2i64: 53 ; CHECK: # BB#0: 54 ; CHECK-NEXT: vmovddup {{.*#+}} xmm1 = mem[0,0] 55 ; CHECK-NEXT: vpaddq %xmm1, %xmm0, %xmm0 56 ; CHECK-NEXT: retq 57 %add = add <2 x i64> %x, <i64 1, i64 1> 58 ret <2 x i64> %add 59 } 60 61 ; AVX can't do 256-bit integer ops, so we split this into two 128-bit vectors, 62 ; and then we fake it: use vmovddup to splat 64-bit value. 63 define <4 x i64> @splat_v4i64(<4 x i64> %x) #0 { 64 ; AVX-LABEL: splat_v4i64: 65 ; AVX: # BB#0: 66 ; AVX-NEXT: vextractf128 $1, %ymm0, %xmm1 67 ; AVX-NEXT: vmovddup {{.*#+}} xmm2 = mem[0,0] 68 ; AVX-NEXT: vpaddq %xmm2, %xmm1, %xmm1 69 ; AVX-NEXT: vpaddq %xmm2, %xmm0, %xmm0 70 ; AVX-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 71 ; AVX-NEXT: retq 72 ; 73 ; AVX2-LABEL: splat_v4i64: 74 ; AVX2: # BB#0: 75 ; AVX2-NEXT: vpbroadcastq {{.*}}(%rip), %ymm1 76 ; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 77 ; AVX2-NEXT: retq 78 %add = add <4 x i64> %x, <i64 1, i64 1, i64 1, i64 1> 79 ret <4 x i64> %add 80 } 81 82 ; AVX can't do integer splats, so fake it: use vbroadcastss to splat 32-bit value. 83 define <4 x i32> @splat_v4i32(<4 x i32> %x) #1 { 84 ; AVX-LABEL: splat_v4i32: 85 ; AVX: # BB#0: 86 ; AVX-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 87 ; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 88 ; AVX-NEXT: retq 89 ; 90 ; AVX2-LABEL: splat_v4i32: 91 ; AVX2: # BB#0: 92 ; AVX2-NEXT: vpbroadcastd {{.*}}(%rip), %xmm1 93 ; AVX2-NEXT: vpaddd %xmm1, %xmm0, %xmm0 94 ; AVX2-NEXT: retq 95 %add = add <4 x i32> %x, <i32 1, i32 1, i32 1, i32 1> 96 ret <4 x i32> %add 97 } 98 99 ; AVX can't do integer splats, so fake it: use vbroadcastss to splat 32-bit value. 100 define <8 x i32> @splat_v8i32(<8 x i32> %x) #0 { 101 ; AVX-LABEL: splat_v8i32: 102 ; AVX: # BB#0: 103 ; AVX-NEXT: vextractf128 $1, %ymm0, %xmm1 104 ; AVX-NEXT: vbroadcastss {{.*}}(%rip), %xmm2 105 ; AVX-NEXT: vpaddd %xmm2, %xmm1, %xmm1 106 ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 107 ; AVX-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 108 ; AVX-NEXT: retq 109 ; 110 ; AVX2-LABEL: splat_v8i32: 111 ; AVX2: # BB#0: 112 ; AVX2-NEXT: vpbroadcastd {{.*}}(%rip), %ymm1 113 ; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 114 ; AVX2-NEXT: retq 115 %add = add <8 x i32> %x, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> 116 ret <8 x i32> %add 117 } 118 119 ; AVX can't do integer splats, and there's no broadcast fakery for 16-bit. Could use pshuflw, etc? 120 define <8 x i16> @splat_v8i16(<8 x i16> %x) #1 { 121 ; AVX-LABEL: splat_v8i16: 122 ; AVX: # BB#0: 123 ; AVX-NEXT: vpaddw {{.*}}(%rip), %xmm0, %xmm0 124 ; AVX-NEXT: retq 125 ; 126 ; AVX2-LABEL: splat_v8i16: 127 ; AVX2: # BB#0: 128 ; AVX2-NEXT: vpbroadcastw {{.*}}(%rip), %xmm1 129 ; AVX2-NEXT: vpaddw %xmm1, %xmm0, %xmm0 130 ; AVX2-NEXT: retq 131 %add = add <8 x i16> %x, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> 132 ret <8 x i16> %add 133 } 134 135 ; AVX can't do integer splats, and there's no broadcast fakery for 16-bit. Could use pshuflw, etc? 136 define <16 x i16> @splat_v16i16(<16 x i16> %x) #0 { 137 ; AVX-LABEL: splat_v16i16: 138 ; AVX: # BB#0: 139 ; AVX-NEXT: vextractf128 $1, %ymm0, %xmm1 140 ; AVX-NEXT: vmovdqa {{.*#+}} xmm2 = [1,1,1,1,1,1,1,1] 141 ; AVX-NEXT: vpaddw %xmm2, %xmm1, %xmm1 142 ; AVX-NEXT: vpaddw %xmm2, %xmm0, %xmm0 143 ; AVX-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 144 ; AVX-NEXT: retq 145 ; 146 ; AVX2-LABEL: splat_v16i16: 147 ; AVX2: # BB#0: 148 ; AVX2-NEXT: vpbroadcastw {{.*}}(%rip), %ymm1 149 ; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 150 ; AVX2-NEXT: retq 151 %add = add <16 x i16> %x, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> 152 ret <16 x i16> %add 153 } 154 155 ; AVX can't do integer splats, and there's no broadcast fakery for 8-bit. Could use pshufb, etc? 156 define <16 x i8> @splat_v16i8(<16 x i8> %x) #1 { 157 ; AVX-LABEL: splat_v16i8: 158 ; AVX: # BB#0: 159 ; AVX-NEXT: vpaddb {{.*}}(%rip), %xmm0, %xmm0 160 ; AVX-NEXT: retq 161 ; 162 ; AVX2-LABEL: splat_v16i8: 163 ; AVX2: # BB#0: 164 ; AVX2-NEXT: vpbroadcastb {{.*}}(%rip), %xmm1 165 ; AVX2-NEXT: vpaddb %xmm1, %xmm0, %xmm0 166 ; AVX2-NEXT: retq 167 %add = add <16 x i8> %x, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> 168 ret <16 x i8> %add 169 } 170 171 ; AVX can't do integer splats, and there's no broadcast fakery for 8-bit. Could use pshufb, etc? 172 define <32 x i8> @splat_v32i8(<32 x i8> %x) #0 { 173 ; AVX-LABEL: splat_v32i8: 174 ; AVX: # BB#0: 175 ; AVX-NEXT: vextractf128 $1, %ymm0, %xmm1 176 ; AVX-NEXT: vmovdqa {{.*#+}} xmm2 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] 177 ; AVX-NEXT: vpaddb %xmm2, %xmm1, %xmm1 178 ; AVX-NEXT: vpaddb %xmm2, %xmm0, %xmm0 179 ; AVX-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 180 ; AVX-NEXT: retq 181 ; 182 ; AVX2-LABEL: splat_v32i8: 183 ; AVX2: # BB#0: 184 ; AVX2-NEXT: vpbroadcastb {{.*}}(%rip), %ymm1 185 ; AVX2-NEXT: vpaddb %ymm1, %ymm0, %ymm0 186 ; AVX2-NEXT: retq 187 %add = add <32 x i8> %x, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> 188 ret <32 x i8> %add 189 } 190 191 ; PR23259: Verify that ISel doesn't crash with a 'fatal error in backend' 192 ; due to a missing AVX pattern to select a v2i64 X86ISD::BROADCAST of a 193 ; loadi64 with multiple uses. 194 195 @A = common global <3 x i64> zeroinitializer, align 32 196 197 define <8 x i64> @pr23259() #1 { 198 entry: 199 %0 = load <4 x i64>, <4 x i64>* bitcast (<3 x i64>* @A to <4 x i64>*), align 32 200 %1 = shufflevector <4 x i64> %0, <4 x i64> undef, <3 x i32> <i32 undef, i32 undef, i32 2> 201 %shuffle = shufflevector <3 x i64> <i64 1, i64 undef, i64 undef>, <3 x i64> %1, <8 x i32> <i32 5, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0> 202 ret <8 x i64> %shuffle 203 } 204 205 attributes #0 = { optsize } 206 attributes #1 = { minsize } 207