1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=slp-vectorizer %s --mtriple=aarch64-- | FileCheck %s 3 4; This test checks whether load-zext-add and load-add reduction patterns 5; get vectorized by SLP. 6 7define i64 @red_zext_ld_2xi64(ptr %ptr) { 8; CHECK-LABEL: @red_zext_ld_2xi64( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR:%.*]], align 1 11; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD0]] to i64 12; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1 13; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[GEP]], align 1 14; CHECK-NEXT: [[ZEXT_1:%.*]] = zext i8 [[LD1]] to i64 15; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[ZEXT]], [[ZEXT_1]] 16; CHECK-NEXT: ret i64 [[ADD_1]] 17; 18entry: 19 %ld0 = load i8, ptr %ptr 20 %zext = zext i8 %ld0 to i64 21 %gep = getelementptr inbounds i8, ptr %ptr, i64 1 22 %ld1 = load i8, ptr %gep 23 %zext.1 = zext i8 %ld1 to i64 24 %add.1 = add nuw nsw i64 %zext, %zext.1 25 ret i64 %add.1 26} 27 28define i64 @red_zext_ld_4xi64(ptr %ptr) { 29; CHECK-LABEL: @red_zext_ld_4xi64( 30; CHECK-NEXT: entry: 31; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[PTR:%.*]], align 1 32; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> 33; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) 34; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[TMP2]] to i64 35; CHECK-NEXT: ret i64 [[TMP3]] 36; 37entry: 38 %ld0 = load i8, ptr %ptr 39 %zext = zext i8 %ld0 to i64 40 %gep = getelementptr inbounds i8, ptr %ptr, i64 1 41 %ld1 = load i8, ptr %gep 42 %zext.1 = zext i8 %ld1 to i64 43 %add.1 = add nuw nsw i64 %zext, %zext.1 44 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2 45 %ld2 = load i8, ptr %gep.1 46 %zext.2 = zext i8 %ld2 to i64 47 %add.2 = add nuw nsw i64 %add.1, %zext.2 48 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3 49 %ld3 = load i8, ptr %gep.2 50 %zext.3 = zext i8 %ld3 to i64 51 %add.3 = add nuw nsw i64 %add.2, %zext.3 52 ret i64 %add.3 53} 54 55define i64 @red_zext_ld_8xi64(ptr %ptr) { 56; CHECK-LABEL: @red_zext_ld_8xi64( 57; CHECK-NEXT: entry: 58; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[PTR:%.*]], align 1 59; CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i64> 60; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> [[TMP1]]) 61; CHECK-NEXT: ret i64 [[TMP2]] 62; 63entry: 64 %ld0 = load i8, ptr %ptr 65 %zext = zext i8 %ld0 to i64 66 %gep = getelementptr inbounds i8, ptr %ptr, i64 1 67 %ld1 = load i8, ptr %gep 68 %zext.1 = zext i8 %ld1 to i64 69 %add.1 = add nuw nsw i64 %zext, %zext.1 70 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2 71 %ld2 = load i8, ptr %gep.1 72 %zext.2 = zext i8 %ld2 to i64 73 %add.2 = add nuw nsw i64 %add.1, %zext.2 74 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3 75 %ld3 = load i8, ptr %gep.2 76 %zext.3 = zext i8 %ld3 to i64 77 %add.3 = add nuw nsw i64 %add.2, %zext.3 78 %gep.3 = getelementptr inbounds i8, ptr %ptr, i64 4 79 %ld4 = load i8, ptr %gep.3 80 %zext.4 = zext i8 %ld4 to i64 81 %add.4 = add nuw nsw i64 %add.3, %zext.4 82 %gep.4 = getelementptr inbounds i8, ptr %ptr, i64 5 83 %ld5 = load i8, ptr %gep.4 84 %zext.5 = zext i8 %ld5 to i64 85 %add.5 = add nuw nsw i64 %add.4, %zext.5 86 %gep.5 = getelementptr inbounds i8, ptr %ptr, i64 6 87 %ld6 = load i8, ptr %gep.5 88 %zext.6 = zext i8 %ld6 to i64 89 %add.6 = add nuw nsw i64 %add.5, %zext.6 90 %gep.6 = getelementptr inbounds i8, ptr %ptr, i64 7 91 %ld7 = load i8, ptr %gep.6 92 %zext.7 = zext i8 %ld7 to i64 93 %add.7 = add nuw nsw i64 %add.6, %zext.7 94 ret i64 %add.7 95} 96 97define i64 @red_zext_ld_16xi64(ptr %ptr) { 98; CHECK-LABEL: @red_zext_ld_16xi64( 99; CHECK-NEXT: entry: 100; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[PTR:%.*]], align 1 101; CHECK-NEXT: [[TMP1:%.*]] = zext <16 x i8> [[TMP0]] to <16 x i64> 102; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> [[TMP1]]) 103; CHECK-NEXT: ret i64 [[TMP2]] 104; 105entry: 106 %ld0 = load i8, ptr %ptr 107 %zext = zext i8 %ld0 to i64 108 %gep = getelementptr inbounds i8, ptr %ptr, i64 1 109 %ld1 = load i8, ptr %gep 110 %zext.1 = zext i8 %ld1 to i64 111 %add.1 = add nuw nsw i64 %zext, %zext.1 112 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2 113 %ld2 = load i8, ptr %gep.1 114 %zext.2 = zext i8 %ld2 to i64 115 %add.2 = add nuw nsw i64 %add.1, %zext.2 116 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3 117 %ld3 = load i8, ptr %gep.2 118 %zext.3 = zext i8 %ld3 to i64 119 %add.3 = add nuw nsw i64 %add.2, %zext.3 120 %gep.3 = getelementptr inbounds i8, ptr %ptr, i64 4 121 %ld4 = load i8, ptr %gep.3 122 %zext.4 = zext i8 %ld4 to i64 123 %add.4 = add nuw nsw i64 %add.3, %zext.4 124 %gep.4 = getelementptr inbounds i8, ptr %ptr, i64 5 125 %ld5 = load i8, ptr %gep.4 126 %zext.5 = zext i8 %ld5 to i64 127 %add.5 = add nuw nsw i64 %add.4, %zext.5 128 %gep.5 = getelementptr inbounds i8, ptr %ptr, i64 6 129 %ld6 = load i8, ptr %gep.5 130 %zext.6 = zext i8 %ld6 to i64 131 %add.6 = add nuw nsw i64 %add.5, %zext.6 132 %gep.6 = getelementptr inbounds i8, ptr %ptr, i64 7 133 %ld7 = load i8, ptr %gep.6 134 %zext.7 = zext i8 %ld7 to i64 135 %add.7 = add nuw nsw i64 %add.6, %zext.7 136 %gep.7 = getelementptr inbounds i8, ptr %ptr, i64 8 137 %ld8 = load i8, ptr %gep.7 138 %zext.8 = zext i8 %ld8 to i64 139 %add.8 = add nuw nsw i64 %add.7, %zext.8 140 %gep.8 = getelementptr inbounds i8, ptr %ptr, i64 9 141 %ld9 = load i8, ptr %gep.8 142 %zext.9 = zext i8 %ld9 to i64 143 %add.9 = add nuw nsw i64 %add.8, %zext.9 144 %gep.9 = getelementptr inbounds i8, ptr %ptr, i64 10 145 %ld10 = load i8, ptr %gep.9 146 %zext.10 = zext i8 %ld10 to i64 147 %add.10 = add nuw nsw i64 %add.9, %zext.10 148 %gep.10 = getelementptr inbounds i8, ptr %ptr, i64 11 149 %ld11 = load i8, ptr %gep.10 150 %zext.11 = zext i8 %ld11 to i64 151 %add.11 = add nuw nsw i64 %add.10, %zext.11 152 %gep.11 = getelementptr inbounds i8, ptr %ptr, i64 12 153 %ld12 = load i8, ptr %gep.11 154 %zext.12 = zext i8 %ld12 to i64 155 %add.12 = add nuw nsw i64 %add.11, %zext.12 156 %gep.12 = getelementptr inbounds i8, ptr %ptr, i64 13 157 %ld13 = load i8, ptr %gep.12 158 %zext.13 = zext i8 %ld13 to i64 159 %add.13 = add nuw nsw i64 %add.12, %zext.13 160 %gep.13 = getelementptr inbounds i8, ptr %ptr, i64 14 161 %ld14 = load i8, ptr %gep.13 162 %zext.14 = zext i8 %ld14 to i64 163 %add.14 = add nuw nsw i64 %add.13, %zext.14 164 %gep.14 = getelementptr inbounds i8, ptr %ptr, i64 15 165 %ld15 = load i8, ptr %gep.14 166 %zext.15 = zext i8 %ld15 to i64 167 %add.15 = add nuw nsw i64 %add.14, %zext.15 168 ret i64 %add.15 169} 170 171 172 173define i64 @red_ld_2xi64(ptr %ptr) { 174; CHECK-LABEL: @red_ld_2xi64( 175; CHECK-NEXT: entry: 176; CHECK-NEXT: [[LD0:%.*]] = load i64, ptr [[PTR:%.*]], align 8 177; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[PTR]], i64 1 178; CHECK-NEXT: [[LD1:%.*]] = load i64, ptr [[GEP]], align 8 179; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[LD0]], [[LD1]] 180; CHECK-NEXT: ret i64 [[ADD_1]] 181; 182entry: 183 %ld0 = load i64, ptr %ptr 184 %gep = getelementptr inbounds i64, ptr %ptr, i64 1 185 %ld1 = load i64, ptr %gep 186 %add.1 = add nuw nsw i64 %ld0, %ld1 187 ret i64 %add.1 188} 189 190define i64 @red_ld_4xi64(ptr %ptr) { 191; CHECK-LABEL: @red_ld_4xi64( 192; CHECK-NEXT: entry: 193; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i64>, ptr [[PTR:%.*]], align 8 194; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> [[TMP0]]) 195; CHECK-NEXT: ret i64 [[TMP1]] 196; 197entry: 198 %ld0 = load i64, ptr %ptr 199 %gep = getelementptr inbounds i64, ptr %ptr, i64 1 200 %ld1 = load i64, ptr %gep 201 %add.1 = add nuw nsw i64 %ld0, %ld1 202 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2 203 %ld2 = load i64, ptr %gep.1 204 %add.2 = add nuw nsw i64 %add.1, %ld2 205 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3 206 %ld3 = load i64, ptr %gep.2 207 %add.3 = add nuw nsw i64 %add.2, %ld3 208 ret i64 %add.3 209} 210 211define i64 @red_ld_8xi64(ptr %ptr) { 212; CHECK-LABEL: @red_ld_8xi64( 213; CHECK-NEXT: entry: 214; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, ptr [[PTR:%.*]], align 8 215; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> [[TMP0]]) 216; CHECK-NEXT: ret i64 [[TMP1]] 217; 218entry: 219 %ld0 = load i64, ptr %ptr 220 %gep = getelementptr inbounds i64, ptr %ptr, i64 1 221 %ld1 = load i64, ptr %gep 222 %add.1 = add nuw nsw i64 %ld0, %ld1 223 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2 224 %ld2 = load i64, ptr %gep.1 225 %add.2 = add nuw nsw i64 %add.1, %ld2 226 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3 227 %ld3 = load i64, ptr %gep.2 228 %add.3 = add nuw nsw i64 %add.2, %ld3 229 %gep.3 = getelementptr inbounds i64, ptr %ptr, i64 4 230 %ld4 = load i64, ptr %gep.3 231 %add.4 = add nuw nsw i64 %add.3, %ld4 232 %gep.4 = getelementptr inbounds i64, ptr %ptr, i64 5 233 %ld5 = load i64, ptr %gep.4 234 %add.5 = add nuw nsw i64 %add.4, %ld5 235 %gep.5 = getelementptr inbounds i64, ptr %ptr, i64 6 236 %ld6 = load i64, ptr %gep.5 237 %add.6 = add nuw nsw i64 %add.5, %ld6 238 %gep.6 = getelementptr inbounds i64, ptr %ptr, i64 7 239 %ld7 = load i64, ptr %gep.6 240 %add.7 = add nuw nsw i64 %add.6, %ld7 241 ret i64 %add.7 242} 243 244define i64 @red_ld_16xi64(ptr %ptr) { 245; CHECK-LABEL: @red_ld_16xi64( 246; CHECK-NEXT: entry: 247; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i64>, ptr [[PTR:%.*]], align 8 248; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> [[TMP0]]) 249; CHECK-NEXT: ret i64 [[TMP1]] 250; 251entry: 252 %ld0 = load i64, ptr %ptr 253 %gep = getelementptr inbounds i64, ptr %ptr, i64 1 254 %ld1 = load i64, ptr %gep 255 %add.1 = add nuw nsw i64 %ld0, %ld1 256 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2 257 %ld2 = load i64, ptr %gep.1 258 %add.2 = add nuw nsw i64 %add.1, %ld2 259 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3 260 %ld3 = load i64, ptr %gep.2 261 %add.3 = add nuw nsw i64 %add.2, %ld3 262 %gep.3 = getelementptr inbounds i64, ptr %ptr, i64 4 263 %ld4 = load i64, ptr %gep.3 264 %add.4 = add nuw nsw i64 %add.3, %ld4 265 %gep.4 = getelementptr inbounds i64, ptr %ptr, i64 5 266 %ld5 = load i64, ptr %gep.4 267 %add.5 = add nuw nsw i64 %add.4, %ld5 268 %gep.5 = getelementptr inbounds i64, ptr %ptr, i64 6 269 %ld6 = load i64, ptr %gep.5 270 %add.6 = add nuw nsw i64 %add.5, %ld6 271 %gep.6 = getelementptr inbounds i64, ptr %ptr, i64 7 272 %ld7 = load i64, ptr %gep.6 273 %add.7 = add nuw nsw i64 %add.6, %ld7 274 %gep.7 = getelementptr inbounds i64, ptr %ptr, i64 8 275 %ld8 = load i64, ptr %gep.7 276 %add.8 = add nuw nsw i64 %add.7, %ld8 277 %gep.8 = getelementptr inbounds i64, ptr %ptr, i64 9 278 %ld9 = load i64, ptr %gep.8 279 %add.9 = add nuw nsw i64 %add.8, %ld9 280 %gep.9 = getelementptr inbounds i64, ptr %ptr, i64 10 281 %ld10 = load i64, ptr %gep.9 282 %add.10 = add nuw nsw i64 %add.9, %ld10 283 %gep.10 = getelementptr inbounds i64, ptr %ptr, i64 11 284 %ld11 = load i64, ptr %gep.10 285 %add.11 = add nuw nsw i64 %add.10, %ld11 286 %gep.11 = getelementptr inbounds i64, ptr %ptr, i64 12 287 %ld12 = load i64, ptr %gep.11 288 %add.12 = add nuw nsw i64 %add.11, %ld12 289 %gep.12 = getelementptr inbounds i64, ptr %ptr, i64 13 290 %ld13 = load i64, ptr %gep.12 291 %add.13 = add nuw nsw i64 %add.12, %ld13 292 %gep.13 = getelementptr inbounds i64, ptr %ptr, i64 14 293 %ld14 = load i64, ptr %gep.13 294 %add.14 = add nuw nsw i64 %add.13, %ld14 295 %gep.14 = getelementptr inbounds i64, ptr %ptr, i64 15 296 %ld15 = load i64, ptr %gep.14 297 %add.15 = add nuw nsw i64 %add.14, %ld15 298 ret i64 %add.15 299} 300