blob: e5181f49751f30dc49e4cd7cf18162f44a0cea26 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -p loop-unroll -mcpu=x86-64-v4 -S %s | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
;; Check that we unroll this loop completely with partial reduction intrinsics
;; in place of plain adds.
define i32 @unroll_partial_rdx(ptr nofree noundef readonly captures(none) %0, ptr nofree noundef readonly captures(none) %1) {
; CHECK-LABEL: define i32 @unroll_partial_rdx(
; CHECK-SAME: ptr nofree noundef readonly captures(none) [[TMP0:%.*]], ptr nofree noundef readonly captures(none) [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 32
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 64
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 96
; CHECK-NEXT: [[TMP5:%.*]] = load <8 x i32>, ptr [[TMP0]], align 4
; CHECK-NEXT: [[TMP6:%.*]] = load <8 x i32>, ptr [[TMP2]], align 4
; CHECK-NEXT: [[TMP7:%.*]] = load <8 x i32>, ptr [[TMP3]], align 4
; CHECK-NEXT: [[TMP8:%.*]] = load <8 x i32>, ptr [[TMP4]], align 4
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 32
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 64
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 96
; CHECK-NEXT: [[TMP12:%.*]] = load <8 x i32>, ptr [[TMP1]], align 4
; CHECK-NEXT: [[TMP13:%.*]] = load <8 x i32>, ptr [[TMP9]], align 4
; CHECK-NEXT: [[TMP14:%.*]] = load <8 x i32>, ptr [[TMP10]], align 4
; CHECK-NEXT: [[TMP15:%.*]] = load <8 x i32>, ptr [[TMP11]], align 4
; CHECK-NEXT: [[TMP16:%.*]] = mul <8 x i32> [[TMP12]], [[TMP5]]
; CHECK-NEXT: [[TMP17:%.*]] = mul <8 x i32> [[TMP13]], [[TMP6]]
; CHECK-NEXT: [[TMP18:%.*]] = mul <8 x i32> [[TMP14]], [[TMP7]]
; CHECK-NEXT: [[TMP19:%.*]] = mul <8 x i32> [[TMP15]], [[TMP8]]
; CHECK-NEXT: [[TMP68:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> zeroinitializer, <8 x i32> [[TMP16]])
; CHECK-NEXT: [[TMP69:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> zeroinitializer, <8 x i32> [[TMP17]])
; CHECK-NEXT: [[TMP70:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> zeroinitializer, <8 x i32> [[TMP18]])
; CHECK-NEXT: [[TMP71:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> zeroinitializer, <8 x i32> [[TMP19]])
; CHECK-NEXT: [[TMP72:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP0]], i64 32
; CHECK-NEXT: [[TMP73:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP72]], i64 32
; CHECK-NEXT: [[TMP74:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP72]], i64 64
; CHECK-NEXT: [[TMP75:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP72]], i64 96
; CHECK-NEXT: [[TMP76:%.*]] = load <8 x i32>, ptr [[TMP72]], align 4
; CHECK-NEXT: [[TMP77:%.*]] = load <8 x i32>, ptr [[TMP73]], align 4
; CHECK-NEXT: [[TMP78:%.*]] = load <8 x i32>, ptr [[TMP74]], align 4
; CHECK-NEXT: [[TMP79:%.*]] = load <8 x i32>, ptr [[TMP75]], align 4
; CHECK-NEXT: [[TMP80:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP1]], i64 32
; CHECK-NEXT: [[TMP81:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP80]], i64 32
; CHECK-NEXT: [[TMP82:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP80]], i64 64
; CHECK-NEXT: [[TMP83:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP80]], i64 96
; CHECK-NEXT: [[TMP84:%.*]] = load <8 x i32>, ptr [[TMP80]], align 4
; CHECK-NEXT: [[TMP85:%.*]] = load <8 x i32>, ptr [[TMP81]], align 4
; CHECK-NEXT: [[TMP86:%.*]] = load <8 x i32>, ptr [[TMP82]], align 4
; CHECK-NEXT: [[TMP87:%.*]] = load <8 x i32>, ptr [[TMP83]], align 4
; CHECK-NEXT: [[TMP88:%.*]] = mul <8 x i32> [[TMP84]], [[TMP76]]
; CHECK-NEXT: [[TMP89:%.*]] = mul <8 x i32> [[TMP85]], [[TMP77]]
; CHECK-NEXT: [[TMP90:%.*]] = mul <8 x i32> [[TMP86]], [[TMP78]]
; CHECK-NEXT: [[TMP91:%.*]] = mul <8 x i32> [[TMP87]], [[TMP79]]
; CHECK-NEXT: [[TMP92:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP68]], <8 x i32> [[TMP88]])
; CHECK-NEXT: [[TMP93:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP69]], <8 x i32> [[TMP89]])
; CHECK-NEXT: [[TMP94:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP70]], <8 x i32> [[TMP90]])
; CHECK-NEXT: [[TMP95:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP71]], <8 x i32> [[TMP91]])
; CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP0]], i64 64
; CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP48]], i64 32
; CHECK-NEXT: [[TMP50:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP48]], i64 64
; CHECK-NEXT: [[TMP51:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP48]], i64 96
; CHECK-NEXT: [[TMP52:%.*]] = load <8 x i32>, ptr [[TMP48]], align 4
; CHECK-NEXT: [[TMP53:%.*]] = load <8 x i32>, ptr [[TMP49]], align 4
; CHECK-NEXT: [[TMP54:%.*]] = load <8 x i32>, ptr [[TMP50]], align 4
; CHECK-NEXT: [[TMP55:%.*]] = load <8 x i32>, ptr [[TMP51]], align 4
; CHECK-NEXT: [[TMP56:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP1]], i64 64
; CHECK-NEXT: [[TMP57:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP56]], i64 32
; CHECK-NEXT: [[TMP58:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP56]], i64 64
; CHECK-NEXT: [[TMP59:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP56]], i64 96
; CHECK-NEXT: [[TMP60:%.*]] = load <8 x i32>, ptr [[TMP56]], align 4
; CHECK-NEXT: [[TMP61:%.*]] = load <8 x i32>, ptr [[TMP57]], align 4
; CHECK-NEXT: [[TMP62:%.*]] = load <8 x i32>, ptr [[TMP58]], align 4
; CHECK-NEXT: [[TMP63:%.*]] = load <8 x i32>, ptr [[TMP59]], align 4
; CHECK-NEXT: [[TMP64:%.*]] = mul <8 x i32> [[TMP60]], [[TMP52]]
; CHECK-NEXT: [[TMP65:%.*]] = mul <8 x i32> [[TMP61]], [[TMP53]]
; CHECK-NEXT: [[TMP66:%.*]] = mul <8 x i32> [[TMP62]], [[TMP54]]
; CHECK-NEXT: [[TMP67:%.*]] = mul <8 x i32> [[TMP63]], [[TMP55]]
; CHECK-NEXT: [[TMP96:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP92]], <8 x i32> [[TMP64]])
; CHECK-NEXT: [[TMP97:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP93]], <8 x i32> [[TMP65]])
; CHECK-NEXT: [[TMP100:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP94]], <8 x i32> [[TMP66]])
; CHECK-NEXT: [[TMP101:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP95]], <8 x i32> [[TMP67]])
; CHECK-NEXT: [[TMP102:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP0]], i64 96
; CHECK-NEXT: [[TMP103:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP102]], i64 32
; CHECK-NEXT: [[TMP104:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP102]], i64 64
; CHECK-NEXT: [[TMP105:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP102]], i64 96
; CHECK-NEXT: [[TMP106:%.*]] = load <8 x i32>, ptr [[TMP102]], align 4
; CHECK-NEXT: [[TMP107:%.*]] = load <8 x i32>, ptr [[TMP103]], align 4
; CHECK-NEXT: [[TMP108:%.*]] = load <8 x i32>, ptr [[TMP104]], align 4
; CHECK-NEXT: [[TMP109:%.*]] = load <8 x i32>, ptr [[TMP105]], align 4
; CHECK-NEXT: [[TMP110:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[TMP1]], i64 96
; CHECK-NEXT: [[TMP111:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP110]], i64 32
; CHECK-NEXT: [[TMP112:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP110]], i64 64
; CHECK-NEXT: [[TMP113:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP110]], i64 96
; CHECK-NEXT: [[TMP114:%.*]] = load <8 x i32>, ptr [[TMP110]], align 4
; CHECK-NEXT: [[TMP115:%.*]] = load <8 x i32>, ptr [[TMP111]], align 4
; CHECK-NEXT: [[TMP116:%.*]] = load <8 x i32>, ptr [[TMP112]], align 4
; CHECK-NEXT: [[TMP117:%.*]] = load <8 x i32>, ptr [[TMP113]], align 4
; CHECK-NEXT: [[TMP118:%.*]] = mul <8 x i32> [[TMP114]], [[TMP106]]
; CHECK-NEXT: [[TMP119:%.*]] = mul <8 x i32> [[TMP115]], [[TMP107]]
; CHECK-NEXT: [[TMP120:%.*]] = mul <8 x i32> [[TMP116]], [[TMP108]]
; CHECK-NEXT: [[TMP121:%.*]] = mul <8 x i32> [[TMP117]], [[TMP109]]
; CHECK-NEXT: [[DOTLCSSA3:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP96]], <8 x i32> [[TMP118]])
; CHECK-NEXT: [[DOTLCSSA2:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP97]], <8 x i32> [[TMP119]])
; CHECK-NEXT: [[DOTLCSSA1:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP100]], <8 x i32> [[TMP120]])
; CHECK-NEXT: [[DOTLCSSA:%.*]] = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> [[TMP101]], <8 x i32> [[TMP121]])
; CHECK-NEXT: [[TMP33:%.*]] = add <8 x i32> [[DOTLCSSA2]], [[DOTLCSSA3]]
; CHECK-NEXT: [[TMP34:%.*]] = add <8 x i32> [[DOTLCSSA1]], [[TMP33]]
; CHECK-NEXT: [[TMP98:%.*]] = add <8 x i32> [[DOTLCSSA]], [[TMP34]]
; CHECK-NEXT: [[TMP99:%.*]] = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP98]])
; CHECK-NEXT: ret i32 [[TMP99]]
;
entry:
br label %loop
loop:
%4 = phi i64 [ 0, %entry ], [ %33, %loop ]
%5 = phi <8 x i32> [ zeroinitializer, %entry ], [ %29, %loop ]
%6 = phi <8 x i32> [ zeroinitializer, %entry ], [ %30, %loop ]
%7 = phi <8 x i32> [ zeroinitializer, %entry ], [ %31, %loop ]
%8 = phi <8 x i32> [ zeroinitializer, %entry ], [ %32, %loop ]
%9 = getelementptr inbounds nuw [4 x i8], ptr %0, i64 %4
%10 = getelementptr inbounds nuw i8, ptr %9, i64 32
%11 = getelementptr inbounds nuw i8, ptr %9, i64 64
%12 = getelementptr inbounds nuw i8, ptr %9, i64 96
%13 = load <8 x i32>, ptr %9, align 4
%14 = load <8 x i32>, ptr %10, align 4
%15 = load <8 x i32>, ptr %11, align 4
%16 = load <8 x i32>, ptr %12, align 4
%17 = getelementptr inbounds nuw [4 x i8], ptr %1, i64 %4
%18 = getelementptr inbounds nuw i8, ptr %17, i64 32
%19 = getelementptr inbounds nuw i8, ptr %17, i64 64
%20 = getelementptr inbounds nuw i8, ptr %17, i64 96
%21 = load <8 x i32>, ptr %17, align 4
%22 = load <8 x i32>, ptr %18, align 4
%23 = load <8 x i32>, ptr %19, align 4
%24 = load <8 x i32>, ptr %20, align 4
%25 = mul <8 x i32> %21, %13
%26 = mul <8 x i32> %22, %14
%27 = mul <8 x i32> %23, %15
%28 = mul <8 x i32> %24, %16
%29 = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> %5, <8 x i32> %25)
%30 = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> %6, <8 x i32> %26)
%31 = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> %7, <8 x i32> %27)
%32 = call <8 x i32> @llvm.vector.partial.reduce.add.v8i32.v8i32(<8 x i32> %8, <8 x i32> %28)
%33 = add nuw i64 %4, 32
%34 = icmp eq i64 %33, 128
br i1 %34, label %exit, label %loop
exit:
%36 = add <8 x i32> %30, %29
%37 = add <8 x i32> %31, %36
%38 = add <8 x i32> %32, %37
%39 = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %38)
ret i32 %39
}