[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}
----------------
zhangweize9-cyber wrote:
Please keep your test cases clean.
https://github.com/llvm/llvm-project/pull/209332
More information about the llvm-commits
mailing list