407 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter "call.*(foo|bar|baz|quux|goo)|extractelement" --version 22; RUN: opt < %s -passes=loop-vectorize -force-vector-interleave=1 -S | FileCheck %s --check-prefixes=NEON3; RUN: opt < %s -passes=loop-vectorize -force-vector-interleave=2 -S | FileCheck %s --check-prefixes=NEON_INTERLEAVE4; RUN: opt < %s -mattr=+sve -passes=loop-vectorize -force-vector-interleave=1 -S | FileCheck %s --check-prefixes=SVE_OR_NEON5; RUN: opt < %s -mattr=+sve -passes=loop-vectorize -force-vector-interleave=2 -S -prefer-predicate-over-epilogue=predicate-dont-vectorize | FileCheck %s --check-prefixes=SVE_OR_NEON_INTERLEAVE6; RUN: opt < %s -mattr=+sve -passes=loop-vectorize -force-vector-interleave=1 -S -prefer-predicate-over-epilogue=predicate-dont-vectorize | FileCheck %s --check-prefixes=SVE_TF7; RUN: opt < %s -mattr=+sve -passes=loop-vectorize -force-vector-interleave=2 -S -prefer-predicate-over-epilogue=predicate-dont-vectorize | FileCheck %s --check-prefixes=SVE_TF_INTERLEAVE8 9target triple = "aarch64-unknown-linux-gnu"10 11; A call whose argument can remain a scalar because it's sequential and only the12; starting value is required.13define void @test_linear8(ptr noalias %a, ptr readnone %b, i64 %n) {14; NEON-LABEL: define void @test_linear815; NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {16; NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR0:[0-9]+]]17;18; NEON_INTERLEAVE-LABEL: define void @test_linear819; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {20; NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR0:[0-9]+]]21;22; SVE_OR_NEON-LABEL: define void @test_linear823; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {24; SVE_OR_NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]25;26; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear827; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {28; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR1:[0-9]+]]29;30; SVE_TF-LABEL: define void @test_linear831; SVE_TF-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {32; SVE_TF: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR1:[0-9]+]]33;34; SVE_TF_INTERLEAVE-LABEL: define void @test_linear835; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {36; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR1:[0-9]+]]37;38entry:39 br label %for.body40 41for.body:42 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]43 %gepb = getelementptr i64, ptr %b, i64 %indvars.iv44 %data = call i64 @foo(ptr %gepb) #045 %gepa = getelementptr inbounds i64, ptr %a, i64 %indvars.iv46 store i64 %data, ptr %gepa47 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 148 %exitcond = icmp eq i64 %indvars.iv.next, %n49 br i1 %exitcond, label %for.cond.cleanup, label %for.body50 51for.cond.cleanup:52 ret void53}54 55define void @test_vector_linear4(ptr noalias %a, ptr readnone %b, ptr readonly %c, i64 %n) {56; NEON-LABEL: define void @test_vector_linear457; NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) {58; NEON: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR1:[0-9]+]]59;60; NEON_INTERLEAVE-LABEL: define void @test_vector_linear461; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) {62; NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR1:[0-9]+]]63;64; SVE_OR_NEON-LABEL: define void @test_vector_linear465; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {66; SVE_OR_NEON: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]67;68; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_vector_linear469; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {70; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]71;72; SVE_TF-LABEL: define void @test_vector_linear473; SVE_TF-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {74; SVE_TF: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]75;76; SVE_TF_INTERLEAVE-LABEL: define void @test_vector_linear477; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {78; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i32 @baz(i32 [[INPUT:%.*]], ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]79;80entry:81 br label %for.body82 83for.body:84 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]85 %gepc = getelementptr i32, ptr %c, i64 %indvars.iv86 %input = load i32, ptr %gepc, align 887 %gepb = getelementptr i32, ptr %b, i64 %indvars.iv88 %data = call i32 @baz(i32 %input, ptr %gepb) #189 %gepa = getelementptr inbounds i32, ptr %a, i64 %indvars.iv90 store i32 %data, ptr %gepa, align 891 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 192 %exitcond = icmp eq i64 %indvars.iv.next, %n93 br i1 %exitcond, label %for.cond.cleanup, label %for.body94 95for.cond.cleanup:96 ret void97}98 99define void @test_linear8_bad_stride(ptr noalias %a, ptr readnone %b, i64 %n) {100; NEON-LABEL: define void @test_linear8_bad_stride101; NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {102; NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]103;104; NEON_INTERLEAVE-LABEL: define void @test_linear8_bad_stride105; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {106; NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR2:[0-9]+]]107;108; SVE_OR_NEON-LABEL: define void @test_linear8_bad_stride109; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {110; SVE_OR_NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR4:[0-9]+]]111;112; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear8_bad_stride113; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {114; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]115;116; SVE_TF-LABEL: define void @test_linear8_bad_stride117; SVE_TF-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {118; SVE_TF: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]119;120; SVE_TF_INTERLEAVE-LABEL: define void @test_linear8_bad_stride121; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {122; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]123;124entry:125 br label %for.body126 127for.body:128 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]129 %gepb = getelementptr i64, ptr %b, i64 %indvars.iv130 %data = call i64 @foo(ptr %gepb) #2131 %gepa = getelementptr inbounds i64, ptr %a, i64 %indvars.iv132 store i64 %data, ptr %gepa133 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1134 %exitcond = icmp eq i64 %indvars.iv.next, %n135 br i1 %exitcond, label %for.cond.cleanup, label %for.body136 137for.cond.cleanup:138 ret void139}140 141define void @test_linear16_wide_stride(ptr noalias %a, ptr readnone %b, i64 %n) {142; NEON-LABEL: define void @test_linear16_wide_stride143; NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {144; NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR2]]145;146; NEON_INTERLEAVE-LABEL: define void @test_linear16_wide_stride147; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) {148; NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR2]]149;150; SVE_OR_NEON-LABEL: define void @test_linear16_wide_stride151; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {152; SVE_OR_NEON: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR4]]153;154; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear16_wide_stride155; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {156; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3]]157;158; SVE_TF-LABEL: define void @test_linear16_wide_stride159; SVE_TF-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {160; SVE_TF: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3]]161;162; SVE_TF_INTERLEAVE-LABEL: define void @test_linear16_wide_stride163; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {164; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i64 @foo(ptr [[GEPB:%.*]]) #[[ATTR3]]165;166entry:167 br label %for.body168 169for.body:170 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]171 %double = mul i64 %indvars.iv, 2172 %gepb = getelementptr i64, ptr %b, i64 %double173 %data = call i64 @foo(ptr %gepb) #2174 %gepa = getelementptr inbounds i64, ptr %a, i64 %indvars.iv175 store i64 %data, ptr %gepa176 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1177 %exitcond = icmp eq i64 %indvars.iv.next, %n178 br i1 %exitcond, label %for.cond.cleanup, label %for.body179 180for.cond.cleanup:181 ret void182}183 184define void @test_linear4_linear8(ptr noalias %a, ptr readnone %b, ptr readonly %c, i64 %n) {185; NEON-LABEL: define void @test_linear4_linear8186; NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) {187; NEON: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]188;189; NEON_INTERLEAVE-LABEL: define void @test_linear4_linear8190; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) {191; NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR3:[0-9]+]]192;193; SVE_OR_NEON-LABEL: define void @test_linear4_linear8194; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {195; SVE_OR_NEON: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR5:[0-9]+]]196;197; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear4_linear8198; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {199; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR4:[0-9]+]]200;201; SVE_TF-LABEL: define void @test_linear4_linear8202; SVE_TF-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {203; SVE_TF: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR4:[0-9]+]]204;205; SVE_TF_INTERLEAVE-LABEL: define void @test_linear4_linear8206; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], ptr readnone [[B:%.*]], ptr readonly [[C:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {207; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i32 @quux(ptr [[GEPC:%.*]], ptr [[GEPB:%.*]]) #[[ATTR4:[0-9]+]]208;209entry:210 br label %for.body211 212for.body:213 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]214 %gepc = getelementptr i32, ptr %c, i64 %indvars.iv215 %gepb = getelementptr i64, ptr %b, i64 %indvars.iv216 %data = call i32 @quux(ptr %gepc, ptr %gepb) #3217 %gepa = getelementptr inbounds i32, ptr %a, i64 %indvars.iv218 store i32 %data, ptr %gepa, align 8219 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1220 %exitcond = icmp eq i64 %indvars.iv.next, %n221 br i1 %exitcond, label %for.cond.cleanup, label %for.body222 223for.cond.cleanup:224 ret void225}226 227define void @test_linear3_non_ptr(ptr noalias %a, i64 %n) {228; NEON-LABEL: define void @test_linear3_non_ptr229; NEON-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) {230; NEON: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1:%.*]], i32 0231; NEON: [[TMP3:%.*]] = call <4 x i32> @vec_bar_linear3_nomask_neon(i32 [[TMP2]])232; NEON: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR4:[0-9]+]]233;234; NEON_INTERLEAVE-LABEL: define void @test_linear3_non_ptr235; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) {236; NEON_INTERLEAVE: [[TMP4:%.*]] = extractelement <4 x i32> [[TMP2:%.*]], i32 0237; NEON_INTERLEAVE: [[TMP5:%.*]] = call <4 x i32> @vec_bar_linear3_nomask_neon(i32 [[TMP4]])238; NEON_INTERLEAVE: [[TMP6:%.*]] = extractelement <4 x i32> [[TMP3:%.*]], i32 0239; NEON_INTERLEAVE: [[TMP7:%.*]] = call <4 x i32> @vec_bar_linear3_nomask_neon(i32 [[TMP6]])240; NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR4:[0-9]+]]241;242; SVE_OR_NEON-LABEL: define void @test_linear3_non_ptr243; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {244; SVE_OR_NEON: [[TMP13:%.*]] = extractelement <vscale x 4 x i32> [[TMP12:%.*]], i32 0245; SVE_OR_NEON: [[TMP14:%.*]] = call <vscale x 4 x i32> @vec_bar_linear3_nomask_sve(i32 [[TMP13]])246; SVE_OR_NEON: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR6:[0-9]+]]247;248; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear3_non_ptr249; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {250; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR5:[0-9]+]]251;252; SVE_TF-LABEL: define void @test_linear3_non_ptr253; SVE_TF-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {254; SVE_TF: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR5:[0-9]+]]255;256; SVE_TF_INTERLEAVE-LABEL: define void @test_linear3_non_ptr257; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {258; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[TREBLED:%.*]]) #[[ATTR5:[0-9]+]]259;260entry:261 br label %for.body262 263for.body:264 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]265 %little.iv = trunc i64 %indvars.iv to i32266 %trebled = mul i32 %little.iv, 3267 %data = call i32 @bar(i32 %trebled) #4268 %gepa = getelementptr inbounds i32, ptr %a, i64 %indvars.iv269 store i32 %data, ptr %gepa270 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1271 %exitcond = icmp eq i64 %indvars.iv.next, %n272 br i1 %exitcond, label %for.cond.cleanup, label %for.body273 274for.cond.cleanup:275 ret void276}277 278define void @test_linearn5_non_ptr_neg_stride(ptr noalias %a, i64 %n) {279; NEON-LABEL: define void @test_linearn5_non_ptr_neg_stride280; NEON-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) {281; NEON: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1:%.*]], i32 0282; NEON: [[TMP3:%.*]] = call <4 x i32> @vec_bar_linearn5_nomask_neon(i32 [[TMP2]])283; NEON: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR5:[0-9]+]]284;285; NEON_INTERLEAVE-LABEL: define void @test_linearn5_non_ptr_neg_stride286; NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) {287; NEON_INTERLEAVE: [[TMP4:%.*]] = extractelement <4 x i32> [[TMP2:%.*]], i32 0288; NEON_INTERLEAVE: [[TMP5:%.*]] = call <4 x i32> @vec_bar_linearn5_nomask_neon(i32 [[TMP4]])289; NEON_INTERLEAVE: [[TMP6:%.*]] = extractelement <4 x i32> [[TMP3:%.*]], i32 0290; NEON_INTERLEAVE: [[TMP7:%.*]] = call <4 x i32> @vec_bar_linearn5_nomask_neon(i32 [[TMP6]])291; NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR5:[0-9]+]]292;293; SVE_OR_NEON-LABEL: define void @test_linearn5_non_ptr_neg_stride294; SVE_OR_NEON-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {295; SVE_OR_NEON: [[TMP13:%.*]] = extractelement <vscale x 4 x i32> [[TMP12:%.*]], i32 0296; SVE_OR_NEON: [[TMP14:%.*]] = call <vscale x 4 x i32> @vec_bar_linearn5_nomask_sve(i32 [[TMP13]])297; SVE_OR_NEON: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR7:[0-9]+]]298;299; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linearn5_non_ptr_neg_stride300; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {301; SVE_OR_NEON_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR6:[0-9]+]]302;303; SVE_TF-LABEL: define void @test_linearn5_non_ptr_neg_stride304; SVE_TF-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {305; SVE_TF: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR6:[0-9]+]]306;307; SVE_TF_INTERLEAVE-LABEL: define void @test_linearn5_non_ptr_neg_stride308; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {309; SVE_TF_INTERLEAVE: [[DATA:%.*]] = call i32 @bar(i32 [[NEGSTRIDE:%.*]]) #[[ATTR6:[0-9]+]]310;311entry:312 br label %for.body313 314for.body:315 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]316 %little.iv = trunc i64 %indvars.iv to i32317 %negstride = mul i32 %little.iv, -5318 %data = call i32 @bar(i32 %negstride) #5319 %gepa = getelementptr inbounds i32, ptr %a, i64 %indvars.iv320 store i32 %data, ptr %gepa321 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1322 %exitcond = icmp eq i64 %indvars.iv.next, %n323 br i1 %exitcond, label %for.cond.cleanup, label %for.body324 325for.cond.cleanup:326 ret void327}328 329define void @test_linear8_return_void(ptr noalias %in, ptr noalias %out, i64 %n) {330; NEON-LABEL: define void @test_linear8_return_void331; NEON-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) {332; NEON: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR6:[0-9]+]]333;334; NEON_INTERLEAVE-LABEL: define void @test_linear8_return_void335; NEON_INTERLEAVE-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) {336; NEON_INTERLEAVE: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR6:[0-9]+]]337;338; SVE_OR_NEON-LABEL: define void @test_linear8_return_void339; SVE_OR_NEON-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {340; SVE_OR_NEON: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR8:[0-9]+]]341;342; SVE_OR_NEON_INTERLEAVE-LABEL: define void @test_linear8_return_void343; SVE_OR_NEON_INTERLEAVE-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {344; SVE_OR_NEON_INTERLEAVE: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR7:[0-9]+]]345;346; SVE_TF-LABEL: define void @test_linear8_return_void347; SVE_TF-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {348; SVE_TF: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR7:[0-9]+]]349;350; SVE_TF_INTERLEAVE-LABEL: define void @test_linear8_return_void351; SVE_TF_INTERLEAVE-SAME: (ptr noalias [[IN:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {352; SVE_TF_INTERLEAVE: call void @goo(i64 [[NUM:%.*]], ptr [[GEP_OUT:%.*]]) #[[ATTR7:[0-9]+]]353;354entry:355 br label %for.body356 357for.body:358 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]359 %gep.in = getelementptr i64, ptr %in, i64 %indvars.iv360 %num = load i64, ptr %gep.in, align 8361 %gep.out = getelementptr i64, ptr %out, i64 %indvars.iv362 call void @goo(i64 %num, ptr %gep.out) #6363 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1364 %exitcond = icmp eq i64 %indvars.iv.next, %n365 br i1 %exitcond, label %for.cond.cleanup, label %for.body366 367for.cond.cleanup:368 ret void369}370 371; Note: Vectorizing pointer arguments is currently disabled as LAA cannot detect372; aliasing from output/input pointers.373 374declare i64 @foo(ptr)375declare i32 @baz(i32, ptr)376declare i32 @quux(ptr, ptr)377declare i32 @bar(i32)378declare void @goo(i64, ptr)379 380; neon vector variants of foo381declare <2 x i64> @vec_foo_linear8_nomask_neon(ptr)382declare <2 x i64> @vec_foo_linear16_nomask_neon(ptr)383declare <4 x i32> @vec_baz_vector_linear4_nomask_neon(<4 x i32>, ptr)384declare <4 x i32> @vec_quux_linear4_linear8_nomask_neon(ptr, ptr)385declare <4 x i32> @vec_bar_linear3_nomask_neon(i32)386declare <4 x i32> @vec_bar_linearn5_nomask_neon(i32)387declare void @vec_goo_linear8_nomask_neon(<2 x i64>, ptr)388 389; scalable vector variants of foo390declare <vscale x 2 x i64> @vec_foo_linear8_mask_sve(ptr, <vscale x 2 x i1>)391declare <vscale x 2 x i64> @vec_foo_linear8_nomask_sve(ptr)392declare <vscale x 2 x i64> @vec_foo_linear16_nomask_sve(ptr)393declare <vscale x 4 x i32> @vec_baz_vector_linear4_nomask_sve(<vscale x 4 x i32>, ptr)394declare <vscale x 4 x i32> @vec_quux_linear4_linear8_mask_sve(ptr, ptr, <vscale x 4 x i1>)395declare <vscale x 4 x i32> @vec_bar_linear3_nomask_sve(i32)396declare <vscale x 4 x i32> @vec_bar_linearn5_nomask_sve(i32)397declare void @vec_goo_linear8_nomask_sve(<vscale x 2 x i64>, ptr)398declare void @vec_goo_linear8_mask_sve(<vscale x 2 x i64>, ptr, <vscale x 2 x i1>)399 400attributes #0 = { nounwind "vector-function-abi-variant"="_ZGVsNxl8_foo(vec_foo_linear8_nomask_sve),_ZGVsMxl8_foo(vec_foo_linear8_mask_sve),_ZGVnN2l8_foo(vec_foo_linear8_nomask_neon)" }401attributes #1 = { nounwind "vector-function-abi-variant"="_ZGVsNxvl4_baz(vec_baz_vector_linear4_nomask_sve),_ZGVnN4vl4_baz(vec_baz_vector_linear4_nomask_neon)" }402attributes #2 = { nounwind "vector-function-abi-variant"="_ZGVsNxl16_foo(vec_foo_linear16_nomask_sve),_ZGVnN2l16_foo(vec_foo_linear16_nomask_neon)" }403attributes #3 = { nounwind "vector-function-abi-variant"="_ZGVsMxl4l8_quux(vec_quux_linear4_linear8_mask_sve),_ZGVnN4l4l8_quux(vec_quux_linear4_linear8_nomask_neon)" }404attributes #4 = { nounwind "vector-function-abi-variant"="_ZGVsNxl3_bar(vec_bar_linear3_nomask_sve),_ZGVnN4l3_bar(vec_bar_linear3_nomask_neon)" }405attributes #5 = { nounwind "vector-function-abi-variant"="_ZGVsNxln5_bar(vec_bar_linearn5_nomask_sve),_ZGVnN4ln5_bar(vec_bar_linearn5_nomask_neon)" }406attributes #6 = { nounwind "vector-function-abi-variant"="_ZGVsNxvl8_goo(vec_goo_linear8_nomask_sve),_ZGVsMxvl8_goo(vec_goo_linear8_mask_sve),_ZGVsN2vl8_goo(vec_goo_linear8_nomask_neon)" }407