1; RUN: opt < %s -mattr=+mve,+mve.fp -loop-vectorize -tail-predication=disabled -S | FileCheck %s --check-prefixes=DEFAULT
2; RUN: opt < %s -mattr=+mve,+mve.fp -loop-vectorize -prefer-predicate-over-epilogue=predicate-else-scalar-epilogue -S | FileCheck %s --check-prefixes=TAILPRED
3
4target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
5target triple = "thumbv8.1m.main-arm-none-eabi"
6
7; When TP is disabled, this test can vectorize with a VF of 16.
8; When TP is enabled, this test should vectorize with a VF of 8.
9;
10; DEFAULT: load <16 x i8>, <16 x i8>*
11; DEFAULT: sext <16 x i8> %{{.*}} to <16 x i16>
12; DEFAULT: add <16 x i16>
13; DEFAULT-NOT: llvm.masked.load
14; DEFAULT-NOT: llvm.masked.store
15;
16; TAILPRED: llvm.masked.load.v8i8.p0v8i8
17; TAILPRED: sext <8 x i8> %{{.*}} to <8 x i16>
18; TAILPRED: add <8 x i16>
19; TAILPRED: call void @llvm.masked.store.v8i8.p0v8i8
20; TAILPRED-NOT: load <16 x i8>, <16 x i8>*
21
22define i32 @tp_reduces_vf(i8* nocapture %0, i32 %1, i8** %input) {
23  %3 = load i8*, i8** %input, align 8
24  %4 = sext i32 %1 to i64
25  %5 = icmp eq i32 %1, 0
26  br i1 %5, label %._crit_edge, label %.preheader47.preheader
27
28.preheader47.preheader:
29  br label %.preheader47
30
31.preheader47:
32  %.050 = phi i64 [ %54, %53 ], [ 0, %.preheader47.preheader ]
33  br label %.preheader
34
35._crit_edge.loopexit:
36  br label %._crit_edge
37
38._crit_edge:
39  ret i32 0
40
41.preheader:
42  %indvars.iv51 = phi i32 [ 1, %.preheader47 ], [ %indvars.iv.next52, %52 ]
43  %6 = mul nuw nsw i32 %indvars.iv51, 320
44  br label %7
45
467:
47  %indvars.iv = phi i32 [ 1, %.preheader ], [ %indvars.iv.next, %7 ]
48  %8 = add nuw nsw i32 %6, %indvars.iv
49  %9 = add nsw i32 %8, -320
50  %10 = add nsw i32 %8, -321
51  %11 = getelementptr inbounds i8, i8* %3, i32 %10
52  %12 = load i8, i8* %11, align 1
53  %13 = sext i8 %12 to i32
54  %14 = getelementptr inbounds i8, i8* %3, i32 %9
55  %15 = load i8, i8* %14, align 1
56  %16 = sext i8 %15 to i32
57  %17 = add nsw i32 %8, -319
58  %18 = getelementptr inbounds i8, i8* %3, i32 %17
59  %19 = load i8, i8* %18, align 1
60  %20 = sext i8 %19 to i32
61  %21 = add nsw i32 %8, -1
62  %22 = getelementptr inbounds i8, i8* %3, i32 %21
63  %23 = load i8, i8* %22, align 1
64  %24 = sext i8 %23 to i32
65  %25 = getelementptr inbounds i8, i8* %3, i32 %8
66  %26 = load i8, i8* %25, align 1
67  %27 = sext i8 %26 to i32
68  %28 = mul nsw i32 %27, 255
69  %29 = add nuw nsw i32 %8, 1
70  %30 = getelementptr inbounds i8, i8* %3, i32 %29
71  %31 = load i8, i8* %30, align 1
72  %32 = sext i8 %31 to i32
73  %33 = add nuw nsw i32 %8, 320
74  %34 = add nuw nsw i32 %8, 319
75  %35 = getelementptr inbounds i8, i8* %3, i32 %34
76  %36 = load i8, i8* %35, align 1
77  %37 = sext i8 %36 to i32
78  %38 = getelementptr inbounds i8, i8* %3, i32 %33
79  %39 = load i8, i8* %38, align 1
80  %40 = sext i8 %39 to i32
81  %41 = add nuw nsw i32 %8, 321
82  %42 = getelementptr inbounds i8, i8* %3, i32 %41
83  %43 = load i8, i8* %42, align 1
84  %44 = sext i8 %43 to i32
85  %reass.add = add nsw i32 %16, %13
86  %reass.add44 = add nsw i32 %reass.add, %20
87  %reass.add45 = add nsw i32 %reass.add44, %24
88  %45 = add nsw i32 %reass.add45, %32
89  %46 = add nsw i32 %45, %37
90  %47 = add nsw i32 %46, %40
91  %reass.add46 = add nsw i32 %47, %44
92  %reass.mul = mul nsw i32 %reass.add46, -28
93  %48 = add nsw i32 %reass.mul, %28
94  %49 = lshr i32 %48, 8
95  %50 = trunc i32 %49 to i8
96  %51 = getelementptr inbounds i8, i8* %0, i32 %8
97  store i8 %50, i8* %51, align 1
98  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
99  %exitcond = icmp eq i32 %indvars.iv.next, 319
100  br i1 %exitcond, label %52, label %7
101
10252:
103  %indvars.iv.next52 = add nuw nsw i32 %indvars.iv51, 1
104  %exitcond53 = icmp eq i32 %indvars.iv.next52, 239
105  br i1 %exitcond53, label %53, label %.preheader
106
10753:
108  %54 = add nuw i64 %.050, 1
109  %55 = icmp ult i64 %54, %4
110  br i1 %55, label %.preheader47, label %._crit_edge.loopexit
111}
112