[llvm] [Passes] Run LoopSimplify before SLP (PR #209332)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 6 06:32:47 PDT 2026


================
@@ -0,0 +1,223 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -O3 < %s | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "aarch64"
+
+; Check that SLP can vectorize both loops.
+
+; Function Attrs: nounwind uwtable
+define dso_local void @pair_sibling_simplified(i32 noundef %n1, i32 noundef %n2, ptr noundef %arr, ptr noundef %out) #0 {
+; CHECK-LABEL: define dso_local void @pair_sibling_simplified(
+; CHECK-SAME: i32 noundef [[N1:%.*]], i32 noundef [[N2:%.*]], ptr nofree noundef readonly captures(none) [[ARR:%.*]], ptr nofree noundef writeonly captures(none) [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[N2]], [[N1]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[XOR]], 1
+; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 4, i32 2
+; CHECK-NEXT:    [[CMP17:%.*]] = icmp ugt i32 [[N1]], 1
+; CHECK-NEXT:    br i1 [[CMP17]], label %[[FOR_BODY:.*]], label %[[FOR_COND6_PREHEADER:.*]]
+; CHECK:       [[FOR_COND6_PREHEADER]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi <2 x double> [ zeroinitializer, %[[ENTRY]] ], [ [[TMP5:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[CMP823:%.*]] = icmp ugt i32 [[N2]], 1
+; CHECK-NEXT:    br i1 [[CMP823]], label %[[FOR_BODY10:.*]], label %[[FOR_COND_CLEANUP9:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[I_020:%.*]] = phi i32 [ [[ADD4:%.*]], %[[FOR_BODY]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = phi <2 x double> [ [[TMP5]], %[[FOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ]
+; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I_020]] to i64
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [8 x i8], ptr [[ARR]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP4:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8, !tbaa [[DOUBLE_TBAA10:![0-9]+]]
+; CHECK-NEXT:    [[TMP5]] = tail call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP4]], <2 x double> splat (double 2.000000e+00), <2 x double> [[TMP3]])
+; CHECK-NEXT:    [[ADD4]] = add i32 [[I_020]], [[COND]]
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i32 [[ADD4]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], [[N1]]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND6_PREHEADER]], !llvm.loop [[LOOP12:![0-9]+]]
+; CHECK:       [[FOR_COND_CLEANUP9]]:
+; CHECK-NEXT:    [[TMP8:%.*]] = phi <2 x double> [ [[TMP0]], %[[FOR_COND6_PREHEADER]] ], [ [[TMP7:%.*]], %[[FOR_BODY10]] ]
+; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <2 x double> [[TMP8]], <2 x double> poison, <2 x i32> <i32 1, i32 poison>
+; CHECK-NEXT:    [[FOLDEXTEXTBINOP:%.*]] = fadd <2 x double> [[SHIFT]], [[TMP8]]
+; CHECK-NEXT:    [[ADD19:%.*]] = extractelement <2 x double> [[FOLDEXTEXTBINOP]], i64 0
+; CHECK-NEXT:    store double [[ADD19]], ptr [[OUT]], align 8, !tbaa [[DOUBLE_TBAA10]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[FOR_BODY10]]:
+; CHECK-NEXT:    [[ADD727:%.*]] = phi i32 [ [[ADD17:%.*]], %[[FOR_BODY10]] ], [ 0, %[[FOR_COND6_PREHEADER]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = phi <2 x double> [ [[TMP7]], %[[FOR_BODY10]] ], [ [[TMP0]], %[[FOR_COND6_PREHEADER]] ]
+; CHECK-NEXT:    [[IDXPROM14:%.*]] = zext i32 [[ADD727]] to i64
+; CHECK-NEXT:    [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw [8 x i8], ptr [[ARR]], i64 [[IDXPROM14]]
+; CHECK-NEXT:    [[TMP6:%.*]] = load <2 x double>, ptr [[ARRAYIDX15]], align 8, !tbaa [[DOUBLE_TBAA10]]
+; CHECK-NEXT:    [[TMP7]] = tail call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP6]], <2 x double> splat (double 4.000000e+00), <2 x double> [[TMP9]])
+; CHECK-NEXT:    [[ADD17]] = add i32 [[ADD727]], [[COND]]
+; CHECK-NEXT:    [[ADD7:%.*]] = or disjoint i32 [[ADD17]], 1
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ult i32 [[ADD7]], [[N2]]
+; CHECK-NEXT:    br i1 [[CMP8]], label %[[FOR_BODY10]], label %[[FOR_COND_CLEANUP9]], !llvm.loop [[LOOP14:![0-9]+]]
+;
+entry:
+  %n1.addr = alloca i32, align 4
+  %n2.addr = alloca i32, align 4
+  %arr.addr = alloca ptr, align 8
+  %out.addr = alloca ptr, align 8
+  %acc0 = alloca double, align 8
+  %acc1 = alloca double, align 8
+  %step = alloca i32, align 4
+  %i = alloca i32, align 4
+  %i5 = alloca i32, align 4
+  store i32 %n1, ptr %n1.addr, align 4, !tbaa !10
+  store i32 %n2, ptr %n2.addr, align 4, !tbaa !10
+  store ptr %arr, ptr %arr.addr, align 8, !tbaa !11
+  store ptr %out, ptr %out.addr, align 8, !tbaa !11
+  call void @llvm.lifetime.start.p0(ptr %acc0) #3
+  store double 0.000000e+00, ptr %acc0, align 8, !tbaa !14
+  call void @llvm.lifetime.start.p0(ptr %acc1) #3
+  store double 0.000000e+00, ptr %acc1, align 8, !tbaa !14
+  call void @llvm.lifetime.start.p0(ptr %step) #3
+  %0 = load i32, ptr %n1.addr, align 4, !tbaa !10
+  %1 = load i32, ptr %n2.addr, align 4, !tbaa !10
+  %xor = xor i32 %0, %1
+  %and = and i32 %xor, 1
+  %tobool = icmp ne i32 %and, 0
+  %2 = zext i1 %tobool to i64
+  %cond = select i1 %tobool, i32 2, i32 4
+  store i32 %cond, ptr %step, align 4, !tbaa !10
+  call void @llvm.lifetime.start.p0(ptr %i) #3
+  store i32 0, ptr %i, align 4, !tbaa !10
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %3 = load i32, ptr %i, align 4, !tbaa !10
+  %add = add i32 %3, 1
+  %4 = load i32, ptr %n1.addr, align 4, !tbaa !10
+  %cmp = icmp ult i32 %add, %4
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  call void @llvm.lifetime.end.p0(ptr %i) #3
+  br label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %5 = load double, ptr %acc0, align 8, !tbaa !14
+  %6 = load ptr, ptr %arr.addr, align 8, !tbaa !11
+  %7 = load i32, ptr %i, align 4, !tbaa !10
+  %idxprom = zext i32 %7 to i64
+  %arrayidx = getelementptr inbounds nuw double, ptr %6, i64 %idxprom
+  %8 = load double, ptr %arrayidx, align 8, !tbaa !14
+  %9 = call double @llvm.fmuladd.f64(double %8, double 2.000000e+00, double %5)
+  store double %9, ptr %acc0, align 8, !tbaa !14
+  %10 = load double, ptr %acc1, align 8, !tbaa !14
+  %11 = load ptr, ptr %arr.addr, align 8, !tbaa !11
+  %12 = load i32, ptr %i, align 4, !tbaa !10
+  %add1 = add i32 %12, 1
+  %idxprom2 = zext i32 %add1 to i64
+  %arrayidx3 = getelementptr inbounds nuw double, ptr %11, i64 %idxprom2
+  %13 = load double, ptr %arrayidx3, align 8, !tbaa !14
+  %14 = call double @llvm.fmuladd.f64(double %13, double 2.000000e+00, double %10)
+  store double %14, ptr %acc1, align 8, !tbaa !14
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %15 = load i32, ptr %step, align 4, !tbaa !10
+  %16 = load i32, ptr %i, align 4, !tbaa !10
+  %add4 = add i32 %16, %15
+  store i32 %add4, ptr %i, align 4, !tbaa !10
+  br label %for.cond, !llvm.loop !16
+
+for.end:                                          ; preds = %for.cond.cleanup
+  call void @llvm.lifetime.start.p0(ptr %i5) #3
+  store i32 0, ptr %i5, align 4, !tbaa !10
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc16, %for.end
+  %17 = load i32, ptr %i5, align 4, !tbaa !10
+  %add7 = add i32 %17, 1
+  %18 = load i32, ptr %n2.addr, align 4, !tbaa !10
+  %cmp8 = icmp ult i32 %add7, %18
+  br i1 %cmp8, label %for.body10, label %for.cond.cleanup9
+
+for.cond.cleanup9:                                ; preds = %for.cond6
+  call void @llvm.lifetime.end.p0(ptr %i5) #3
+  br label %for.end18
+
+for.body10:                                       ; preds = %for.cond6
+  %19 = load double, ptr %acc0, align 8, !tbaa !14
+  %20 = load ptr, ptr %arr.addr, align 8, !tbaa !11
+  %21 = load i32, ptr %i5, align 4, !tbaa !10
+  %idxprom11 = zext i32 %21 to i64
+  %arrayidx12 = getelementptr inbounds nuw double, ptr %20, i64 %idxprom11
+  %22 = load double, ptr %arrayidx12, align 8, !tbaa !14
+  %23 = call double @llvm.fmuladd.f64(double %22, double 4.000000e+00, double %19)
+  store double %23, ptr %acc0, align 8, !tbaa !14
+  %24 = load double, ptr %acc1, align 8, !tbaa !14
+  %25 = load ptr, ptr %arr.addr, align 8, !tbaa !11
+  %26 = load i32, ptr %i5, align 4, !tbaa !10
+  %add13 = add i32 %26, 1
+  %idxprom14 = zext i32 %add13 to i64
+  %arrayidx15 = getelementptr inbounds nuw double, ptr %25, i64 %idxprom14
+  %27 = load double, ptr %arrayidx15, align 8, !tbaa !14
+  %28 = call double @llvm.fmuladd.f64(double %27, double 4.000000e+00, double %24)
+  store double %28, ptr %acc1, align 8, !tbaa !14
+  br label %for.inc16
+
+for.inc16:                                        ; preds = %for.body10
+  %29 = load i32, ptr %step, align 4, !tbaa !10
+  %30 = load i32, ptr %i5, align 4, !tbaa !10
+  %add17 = add i32 %30, %29
+  store i32 %add17, ptr %i5, align 4, !tbaa !10
+  br label %for.cond6, !llvm.loop !18
+
+for.end18:                                        ; preds = %for.cond.cleanup9
+  %31 = load double, ptr %acc0, align 8, !tbaa !14
+  %32 = load double, ptr %acc1, align 8, !tbaa !14
+  %add19 = fadd double %31, %32
+  %33 = load ptr, ptr %out.addr, align 8, !tbaa !11
+  store double %add19, ptr %33, align 8, !tbaa !14
+  call void @llvm.lifetime.end.p0(ptr %step) #3
+  call void @llvm.lifetime.end.p0(ptr %acc1) #3
+  call void @llvm.lifetime.end.p0(ptr %acc0) #3
+  ret void
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.start.p0(ptr captures(none)) #1
+
+; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)
+declare double @llvm.fmuladd.f64(double, double, double) #2
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.end.p0(ptr captures(none)) #1
+
+attributes #0 = { nounwind uwtable "frame-pointer"="non-leaf-no-reserve" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a,-fmv" }
+attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+attributes #2 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #3 = { nounwind }
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+!llvm.ident = !{!4}
+!llvm.errno.tbaa = !{!5}
+
+!0 = !{i32 8, !"PIC Level", i32 2}
+!1 = !{i32 7, !"PIE Level", i32 2}
+!2 = !{i32 7, !"uwtable", i32 2}
+!3 = !{i32 7, !"frame-pointer", i32 4}
+!4 = !{!"clang version 23.0.0git (git at github.com:hazzlim/llvm-project.git dc8ee15f2bbc5b18316f071c5ae746bd95609ade)"}
+!5 = !{!6, !7, i64 0}
+!6 = !{!"__libc_errno", !7, i64 0}
+!7 = !{!"int", !8, i64 0}
+!8 = !{!"omnipotent char", !9, i64 0}
+!9 = !{!"Simple C/C++ TBAA"}
+!10 = !{!7, !7, i64 0}
+!11 = !{!12, !12, i64 0}
+!12 = !{!"p1 double", !13, i64 0}
+!13 = !{!"any pointer", !8, i64 0}
+!14 = !{!15, !15, i64 0}
+!15 = !{!"double", !8, i64 0}
+!16 = distinct !{!16, !17}
+!17 = !{!"llvm.loop.mustprogress"}
+!18 = distinct !{!18, !17}
----------------
zhangweize9-cyber wrote:

This part is actually deduced by the compiler itself, and it's not recommended to retain it in test cases.

Also, take a look at line 200; your repository commit hash is now displayed there.

https://github.com/llvm/llvm-project/pull/209332


More information about the llvm-commits mailing list