1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=slp-vectorizer -S -mtriple=aarch64-unknown-unknown -mcpu=cortex-a53 | FileCheck %s 3 4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5 6; This test is reduced from the TSVC evaluation of vectorizers: 7; https://github.com/llvm/llvm-test-suite/commits/main/MultiSource/Benchmarks/TSVC/LoopRerolling-flt/tsc.c 8; Two loads and an fmul are expected to be vectorized to <2 x float>. 9; Otherwise, performance will suffer on Cortex-A53. 10; See https://bugs.llvm.org/show_bug.cgi?id=36280 for more details. 11 12%struct.GlobalData = type { [32000 x float], [3 x i32], [4 x i8], [32000 x float], [5 x i32], [12 x i8], [32000 x float], [7 x i32], [4 x i8], [32000 x float], [11 x i32], [4 x i8], [32000 x float], [13 x i32], [12 x i8], [256 x [256 x float]], [17 x i32], [12 x i8], [256 x [256 x float]], [19 x i32], [4 x i8], [256 x [256 x float]], [23 x i32], [4 x i8], [256 x [256 x float]] } 13 14@global_data = common dso_local global %struct.GlobalData zeroinitializer, align 16 15 16define i32 @s352() { 17; CHECK-LABEL: @s352( 18; CHECK-NEXT: entry: 19; CHECK-NEXT: br label [[PREHEADER:%.*]] 20; CHECK: preheader: 21; CHECK-NEXT: [[NL_017:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND_CLEANUP3:%.*]] ] 22; CHECK-NEXT: br label [[FOR_BODY:%.*]] 23; CHECK: for.cond.cleanup: 24; CHECK-NEXT: ret i32 0 25; CHECK: for.cond.cleanup3: 26; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[NL_017]], 1 27; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1600000 28; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[PREHEADER]] 29; CHECK: for.body: 30; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 31; CHECK-NEXT: [[DOT_115:%.*]] = phi float [ 0.000000e+00, [[PREHEADER]] ], [ [[ADD39:%.*]], [[FOR_BODY]] ] 32; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA:%.*]], ptr @global_data, i64 0, i32 0, i64 [[INDVARS_IV]] 33; CHECK-NEXT: [[ARRAYIDX6:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA]], ptr @global_data, i64 0, i32 3, i64 [[INDVARS_IV]] 34; CHECK-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr [[ARRAYIDX]], align 4 35; CHECK-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr [[ARRAYIDX6]], align 4 36; CHECK-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]] 37; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[TMP4]], i32 0 38; CHECK-NEXT: [[ADD:%.*]] = fadd float [[DOT_115]], [[TMP5]] 39; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[TMP4]], i32 1 40; CHECK-NEXT: [[ADD15:%.*]] = fadd float [[ADD]], [[TMP6]] 41; CHECK-NEXT: [[TMP7:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2 42; CHECK-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA]], ptr @global_data, i64 0, i32 0, i64 [[TMP7]] 43; CHECK-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA]], ptr @global_data, i64 0, i32 3, i64 [[TMP7]] 44; CHECK-NEXT: [[TMP9:%.*]] = load <2 x float>, ptr [[ARRAYIDX18]], align 4 45; CHECK-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[ARRAYIDX21]], align 4 46; CHECK-NEXT: [[TMP12:%.*]] = fmul <2 x float> [[TMP9]], [[TMP11]] 47; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[TMP12]], i32 0 48; CHECK-NEXT: [[ADD23:%.*]] = fadd float [[ADD15]], [[TMP13]] 49; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[TMP12]], i32 1 50; CHECK-NEXT: [[ADD31:%.*]] = fadd float [[ADD23]], [[TMP14]] 51; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 4 52; CHECK-NEXT: [[ARRAYIDX34:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA]], ptr @global_data, i64 0, i32 0, i64 [[TMP15]] 53; CHECK-NEXT: [[TMP16:%.*]] = load float, ptr [[ARRAYIDX34]], align 4 54; CHECK-NEXT: [[ARRAYIDX37:%.*]] = getelementptr inbounds [[STRUCT_GLOBALDATA]], ptr @global_data, i64 0, i32 3, i64 [[TMP15]] 55; CHECK-NEXT: [[TMP17:%.*]] = load float, ptr [[ARRAYIDX37]], align 4 56; CHECK-NEXT: [[MUL38:%.*]] = fmul float [[TMP16]], [[TMP17]] 57; CHECK-NEXT: [[ADD39]] = fadd float [[ADD31]], [[MUL38]] 58; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5 59; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT]], 32000 60; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP3]] 61; 62entry: 63 br label %preheader 64 65preheader: 66 %nl.017 = phi i32 [ 0, %entry ], [ %inc, %for.cond.cleanup3 ] 67 br label %for.body 68 69for.cond.cleanup: 70 ret i32 0 71 72for.cond.cleanup3: 73 %inc = add nuw nsw i32 %nl.017, 1 74 %exitcond = icmp eq i32 %inc, 1600000 75 br i1 %exitcond, label %for.cond.cleanup, label %preheader 76 77for.body: 78 %indvars.iv = phi i64 [ 0, %preheader ], [ %indvars.iv.next, %for.body ] 79 %dot.115 = phi float [ 0.000000e+00, %preheader ], [ %add39, %for.body ] 80 %arrayidx = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 0, i64 %indvars.iv 81 %0 = load float, ptr %arrayidx, align 4 82 %arrayidx6 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 3, i64 %indvars.iv 83 %1 = load float, ptr %arrayidx6, align 4 84 %mul7 = fmul float %0, %1 85 %add = fadd float %dot.115, %mul7 86 %2 = add nuw nsw i64 %indvars.iv, 1 87 %arrayidx10 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 0, i64 %2 88 %3 = load float, ptr %arrayidx10, align 4 89 %arrayidx13 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 3, i64 %2 90 %4 = load float, ptr %arrayidx13, align 4 91 %mul14 = fmul float %3, %4 92 %add15 = fadd float %add, %mul14 93 %5 = add nuw nsw i64 %indvars.iv, 2 94 %arrayidx18 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 0, i64 %5 95 %6 = load float, ptr %arrayidx18, align 4 96 %arrayidx21 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 3, i64 %5 97 %7 = load float, ptr %arrayidx21, align 4 98 %mul22 = fmul float %6, %7 99 %add23 = fadd float %add15, %mul22 100 %8 = add nuw nsw i64 %indvars.iv, 3 101 %arrayidx26 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 0, i64 %8 102 %9 = load float, ptr %arrayidx26, align 4 103 %arrayidx29 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 3, i64 %8 104 %10 = load float, ptr %arrayidx29, align 4 105 %mul30 = fmul float %9, %10 106 %add31 = fadd float %add23, %mul30 107 %11 = add nuw nsw i64 %indvars.iv, 4 108 %arrayidx34 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 0, i64 %11 109 %12 = load float, ptr %arrayidx34, align 4 110 %arrayidx37 = getelementptr inbounds %struct.GlobalData, ptr @global_data, i64 0, i32 3, i64 %11 111 %13 = load float, ptr %arrayidx37, align 4 112 %mul38 = fmul float %12, %13 113 %add39 = fadd float %add31, %mul38 114 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 5 115 %cmp2 = icmp ult i64 %indvars.iv.next, 32000 116 br i1 %cmp2, label %for.body, label %for.cond.cleanup3 117} 118 119