109 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=slp-vectorizer -S | FileCheck %s3 4target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"5target triple = "aarch64--linux-gnu"6 7; These examples correspond to input code like:8;9; void t(long * __restrict a, long * __restrict b) {10; aptr= b[0];11; aptr= b[1];12; }13;14; If we SLP vectorise this then we end up with something like this because we15; don't have a mul.2d:16;17; ldr q0, [x1]18; ldr q1, [x0]19; fmov x8, d020; mov x10, v0.d[1]21; fmov x9, d122; mov x11, v1.d[1]23; mul x8, x9, x824; mul x9, x11, x1025; fmov d0, x826; mov v0.d[1], x927; str q0, [x0]28; ret29;30; If we don't SLP vectorise but scalarize this we get this instead:31;32; ldp x8, x9, [x1]33; ldp x10, x11, [x0]34; mul x9, x11, x935; mul x8, x10, x836; stp x8, x9, [x0]37; ret38;39define void @mul(ptr noalias nocapture %a, ptr noalias nocapture readonly %b) {40; CHECK-LABEL: @mul(41; CHECK-NEXT: entry:42; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[B:%.*]], align 843; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[A:%.*]], align 844; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP1]], [[TMP0]]45; CHECK-NEXT: store i64 [[MUL]], ptr [[A]], align 846; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 147; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARRAYIDX2]], align 848; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 149; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX3]], align 850; CHECK-NEXT: [[MUL4:%.*]] = mul nsw i64 [[TMP3]], [[TMP2]]51; CHECK-NEXT: store i64 [[MUL4]], ptr [[ARRAYIDX3]], align 852; CHECK-NEXT: ret void53;54entry:55 %0 = load i64, ptr %b, align 856 %1 = load i64, ptr %a, align 857 %mul = mul nsw i64 %1, %058 store i64 %mul, ptr %a, align 859 %arrayidx2 = getelementptr inbounds i64, ptr %b, i64 160 %2 = load i64, ptr %arrayidx2, align 861 %arrayidx3 = getelementptr inbounds i64, ptr %a, i64 162 %3 = load i64, ptr %arrayidx3, align 863 %mul4 = mul nsw i64 %3, %264 store i64 %mul4, ptr %arrayidx3, align 865 ret void66}67 68; Similar example, but now a multiply-accumulate:69;70; void x (long * __restrict a, long * __restrict b) {71; aptr= b[0];72; aptr= b[1];73; a[0] += b[0];74; a[1] += b[1];75; }76;77define void @mac(ptr noalias nocapture %a, ptr noalias nocapture readonly %b) {78; CHECK-LABEL: @mac(79; CHECK-NEXT: entry:80; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[B:%.*]], align 881; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[A:%.*]], align 882; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP1]], [[TMP0]]83; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 184; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARRAYIDX2]], align 885; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 186; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX3]], align 887; CHECK-NEXT: [[MUL4:%.*]] = mul nsw i64 [[TMP3]], [[TMP2]]88; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], [[TMP0]]89; CHECK-NEXT: store i64 [[ADD]], ptr [[A]], align 890; CHECK-NEXT: [[ADD9:%.*]] = add nsw i64 [[MUL4]], [[TMP2]]91; CHECK-NEXT: store i64 [[ADD9]], ptr [[ARRAYIDX3]], align 892; CHECK-NEXT: ret void93;94entry:95 %0 = load i64, ptr %b, align 896 %1 = load i64, ptr %a, align 897 %mul = mul nsw i64 %1, %098 %arrayidx2 = getelementptr inbounds i64, ptr %b, i64 199 %2 = load i64, ptr %arrayidx2, align 8100 %arrayidx3 = getelementptr inbounds i64, ptr %a, i64 1101 %3 = load i64, ptr %arrayidx3, align 8102 %mul4 = mul nsw i64 %3, %2103 %add = add nsw i64 %mul, %0104 store i64 %add, ptr %a, align 8105 %add9 = add nsw i64 %mul4, %2106 store i64 %add9, ptr %arrayidx3, align 8107 ret void108}109