| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s | |
| define void @test(ptr noalias %a, ptr noalias %b, ptr noalias %c) { | |
| ; CHECK-LABEL: define void @test( | |
| ; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[OUTER:.*]] | |
| ; CHECK: [[OUTER]]: | |
| ; CHECK-NEXT: [[QZ:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[QZ_NEXT:%.*]], %[[OUTER_LATCH:.*]] ] | |
| ; CHECK-NEXT: [[ABASE:%.*]] = mul i64 [[QZ]], 12 | |
| ; CHECK-NEXT: [[PA00:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[ABASE]] | |
| ; CHECK-NEXT: [[PA10:%.*]] = getelementptr inbounds double, ptr [[PA00]], i64 3 | |
| ; CHECK-NEXT: [[PA20:%.*]] = getelementptr inbounds double, ptr [[PA00]], i64 6 | |
| ; CHECK-NEXT: [[PA30:%.*]] = getelementptr inbounds double, ptr [[PA00]], i64 9 | |
| ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[PA00]], align 8 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[PA10]], align 8 | |
| ; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[PA20]], align 8 | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr [[PA30]], align 8 | |
| ; CHECK-NEXT: [[CBASE:%.*]] = mul i64 [[QZ]], 6 | |
| ; CHECK-NEXT: br label %[[INNER:.*]] | |
| ; CHECK: [[INNER]]: | |
| ; CHECK-NEXT: [[DY:%.*]] = phi i64 [ 0, %[[OUTER]] ], [ [[DY_NEXT:%.*]], %[[INNER]] ] | |
| ; CHECK-NEXT: [[PB0:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[DY]] | |
| ; CHECK-NEXT: [[S0:%.*]] = load double, ptr [[PB0]], align 8 | |
| ; CHECK-NEXT: [[PB1:%.*]] = getelementptr inbounds double, ptr [[PB0]], i64 3 | |
| ; CHECK-NEXT: [[S1:%.*]] = load double, ptr [[PB1]], align 8 | |
| ; CHECK-NEXT: [[PB2:%.*]] = getelementptr inbounds double, ptr [[PB0]], i64 6 | |
| ; CHECK-NEXT: [[S2:%.*]] = load double, ptr [[PB2]], align 8 | |
| ; CHECK-NEXT: [[PB3:%.*]] = getelementptr inbounds double, ptr [[PB0]], i64 9 | |
| ; CHECK-NEXT: [[S3:%.*]] = load double, ptr [[PB3]], align 8 | |
| ; CHECK-NEXT: [[DY2:%.*]] = shl i64 [[DY]], 1 | |
| ; CHECK-NEXT: [[CIDX:%.*]] = add i64 [[CBASE]], [[DY2]] | |
| ; CHECK-NEXT: [[PC0:%.*]] = getelementptr inbounds double, ptr [[C]], i64 [[CIDX]] | |
| ; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x double> poison, double [[S0]], i64 0 | |
| ; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <2 x i32> zeroinitializer | |
| ; CHECK-NEXT: [[TMP6:%.*]] = fmul fast <2 x double> [[TMP0]], [[TMP5]] | |
| ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> poison, double [[S1]], i64 0 | |
| ; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <2 x i32> zeroinitializer | |
| ; CHECK-NEXT: [[TMP9:%.*]] = fmul fast <2 x double> [[TMP1]], [[TMP8]] | |
| ; CHECK-NEXT: [[TMP10:%.*]] = fadd fast <2 x double> [[TMP9]], [[TMP6]] | |
| ; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x double> poison, double [[S2]], i64 0 | |
| ; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <2 x double> [[TMP11]], <2 x double> poison, <2 x i32> zeroinitializer | |
| ; CHECK-NEXT: [[TMP13:%.*]] = fmul fast <2 x double> [[TMP2]], [[TMP12]] | |
| ; CHECK-NEXT: [[TMP14:%.*]] = fadd fast <2 x double> [[TMP13]], [[TMP10]] | |
| ; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x double> poison, double [[S3]], i64 0 | |
| ; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <2 x double> [[TMP15]], <2 x double> poison, <2 x i32> zeroinitializer | |
| ; CHECK-NEXT: [[TMP17:%.*]] = fmul fast <2 x double> [[TMP3]], [[TMP16]] | |
| ; CHECK-NEXT: [[TMP18:%.*]] = fadd fast <2 x double> [[TMP17]], [[TMP14]] | |
| ; CHECK-NEXT: store <2 x double> [[TMP18]], ptr [[PC0]], align 8 | |
| ; CHECK-NEXT: [[DY_NEXT]] = add nuw nsw i64 [[DY]], 1 | |
| ; CHECK-NEXT: [[DY_CMP:%.*]] = icmp ult i64 [[DY_NEXT]], 3 | |
| ; CHECK-NEXT: br i1 [[DY_CMP]], label %[[INNER]], label %[[OUTER_LATCH]] | |
| ; CHECK: [[OUTER_LATCH]]: | |
| ; CHECK-NEXT: [[QZ_NEXT]] = add nuw nsw i64 [[QZ]], 1 | |
| ; CHECK-NEXT: [[QZ_CMP:%.*]] = icmp ult i64 [[QZ_NEXT]], 4 | |
| ; CHECK-NEXT: br i1 [[QZ_CMP]], label %[[OUTER]], label %[[EXIT:.*]] | |
| ; CHECK: [[EXIT]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %outer | |
| outer: | |
| %qz = phi i64 [ 0, %entry ], [ %qz.next, %outer.latch ] | |
| %abase = mul i64 %qz, 12 | |
| %pa00 = getelementptr inbounds double, ptr %a, i64 %abase | |
| %a00 = load double, ptr %pa00, align 8 | |
| %pa01 = getelementptr inbounds double, ptr %pa00, i64 1 | |
| %a01 = load double, ptr %pa01, align 8 | |
| %pa10 = getelementptr inbounds double, ptr %pa00, i64 3 | |
| %a10 = load double, ptr %pa10, align 8 | |
| %pa11 = getelementptr inbounds double, ptr %pa00, i64 4 | |
| %a11 = load double, ptr %pa11, align 8 | |
| %pa20 = getelementptr inbounds double, ptr %pa00, i64 6 | |
| %a20 = load double, ptr %pa20, align 8 | |
| %pa21 = getelementptr inbounds double, ptr %pa00, i64 7 | |
| %a21 = load double, ptr %pa21, align 8 | |
| %pa30 = getelementptr inbounds double, ptr %pa00, i64 9 | |
| %a30 = load double, ptr %pa30, align 8 | |
| %pa31 = getelementptr inbounds double, ptr %pa00, i64 10 | |
| %a31 = load double, ptr %pa31, align 8 | |
| %cbase = mul i64 %qz, 6 | |
| br label %inner | |
| inner: | |
| %dy = phi i64 [ 0, %outer ], [ %dy.next, %inner ] | |
| %pb0 = getelementptr inbounds double, ptr %b, i64 %dy | |
| %s0 = load double, ptr %pb0, align 8 | |
| %pb1 = getelementptr inbounds double, ptr %pb0, i64 3 | |
| %s1 = load double, ptr %pb1, align 8 | |
| %pb2 = getelementptr inbounds double, ptr %pb0, i64 6 | |
| %s2 = load double, ptr %pb2, align 8 | |
| %pb3 = getelementptr inbounds double, ptr %pb0, i64 9 | |
| %s3 = load double, ptr %pb3, align 8 | |
| %m00 = fmul fast double %a00, %s0 | |
| %m10 = fmul fast double %a10, %s1 | |
| %u10 = fadd fast double %m10, %m00 | |
| %m20 = fmul fast double %a20, %s2 | |
| %u20 = fadd fast double %m20, %u10 | |
| %m30 = fmul fast double %a30, %s3 | |
| %u0 = fadd fast double %m30, %u20 | |
| %m01 = fmul fast double %a01, %s0 | |
| %m11 = fmul fast double %a11, %s1 | |
| %u11 = fadd fast double %m11, %m01 | |
| %m21 = fmul fast double %a21, %s2 | |
| %u21 = fadd fast double %m21, %u11 | |
| %m31 = fmul fast double %a31, %s3 | |
| %u1 = fadd fast double %m31, %u21 | |
| %dy2 = shl i64 %dy, 1 | |
| %cidx = add i64 %cbase, %dy2 | |
| %pc0 = getelementptr inbounds double, ptr %c, i64 %cidx | |
| store double %u0, ptr %pc0, align 8 | |
| %pc1 = getelementptr inbounds double, ptr %pc0, i64 1 | |
| store double %u1, ptr %pc1, align 8 | |
| %dy.next = add nuw nsw i64 %dy, 1 | |
| %dy.cmp = icmp ult i64 %dy.next, 3 | |
| br i1 %dy.cmp, label %inner, label %outer.latch | |
| outer.latch: | |
| %qz.next = add nuw nsw i64 %qz, 1 | |
| %qz.cmp = icmp ult i64 %qz.next, 4 | |
| br i1 %qz.cmp, label %outer, label %exit | |
| exit: | |
| ret void | |
| } |