blob: aa5a0f5be24be81388cc019f917ca9467f9b082e [file]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -p loop-vectorize -S %s | FileCheck %s
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"
define void @test_free_instructions_feeding_geps_for_interleave_groups(ptr noalias %p.invar, ptr noalias %dst.1, ptr noalias %dst.2) {
; CHECK-LABEL: define void @test_free_instructions_feeding_geps_for_interleave_groups(
; CHECK-SAME: ptr noalias [[P_INVAR:%.*]], ptr noalias [[DST_1:%.*]], ptr noalias [[DST_2:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[P_INVAR]], align 4
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[TMP0]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[INDEX]], 2
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[P_INVAR]], align 4
; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT1]], <2 x float> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLAT]], <2 x float> [[BROADCAST_SPLAT2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <8 x float> [[TMP5]], <8 x float> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
; CHECK-NEXT: store <8 x float> [[INTERLEAVED_VEC]], ptr [[TMP2]], align 4
; CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[P_INVAR]], align 4
; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <2 x float> poison, float [[TMP6]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT3]], <2 x float> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[TMP1]]
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLAT4]], <2 x float> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x float> [[TMP8]], <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
; CHECK-NEXT: [[INTERLEAVED_VEC5:%.*]] = shufflevector <8 x float> [[TMP9]], <8 x float> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
; CHECK-NEXT: store <8 x float> [[INTERLEAVED_VEC5]], ptr [[TMP7]], align 4
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%l.0 = load float, ptr %p.invar, align 4
%iv.mul = shl i64 %iv, 2
%gep.dst.19 = getelementptr float, ptr %dst.1, i64 %iv.mul
store float %l.0, ptr %gep.dst.19, align 4
%l.1 = load float, ptr %p.invar, align 4
%add.1 = or disjoint i64 %iv.mul, 1
%gep.dst.119 = getelementptr float, ptr %dst.1, i64 %add.1
store float %l.1, ptr %gep.dst.119, align 4
%add.2 = or disjoint i64 %iv.mul, 2
%gep.dst.129 = getelementptr float, ptr %dst.1, i64 %add.2
store float 0.000000e+00, ptr %gep.dst.129, align 4
%add.3 = or disjoint i64 %iv.mul, 3
%gep.dst.140 = getelementptr float, ptr %dst.1, i64 %add.3
store float 0.000000e+00, ptr %gep.dst.140, align 4
%l.2 = load float, ptr %p.invar, align 4
%gep.dst.247 = getelementptr float, ptr %dst.2, i64 %iv.mul
store float %l.2, ptr %gep.dst.247, align 4
%gep.dst.255 = getelementptr float, ptr %dst.2, i64 %add.1
store float 0.000000e+00, ptr %gep.dst.255, align 4
%gep.dst.265 = getelementptr float, ptr %dst.2, i64 %add.2
store float 0.000000e+00, ptr %gep.dst.265, align 4
%gep.dst.276 = getelementptr float, ptr %dst.2, i64 %add.3
store float 0.000000e+00, ptr %gep.dst.276, align 4
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv.next, 1024
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @geps_feeding_interleave_groups_with_reuse(ptr %arg, i64 %arg1, ptr %arg2) #0 {
; CHECK-LABEL: define void @geps_feeding_interleave_groups_with_reuse(
; CHECK-SAME: ptr [[ARG:%.*]], i64 [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[SHL_IV_5:%.*]] = shl i64 [[IV]], 5
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 [[SHL_IV_5]]
; CHECK-NEXT: [[ADD_5:%.*]] = or disjoint i64 [[SHL_IV_5]], 16
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[ADD_5]]
; CHECK-NEXT: [[SHL_IV_4:%.*]] = shl i64 [[IV]], 4
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 [[SHL_IV_4]]
; CHECK-NEXT: [[L_1:%.*]] = load float, ptr [[GEP_1]], align 4
; CHECK-NEXT: [[L_2:%.*]] = load float, ptr [[GEP_2]], align 4
; CHECK-NEXT: [[ADD_1:%.*]] = fadd float [[L_1]], [[L_2]]
; CHECK-NEXT: [[MUL_1:%.*]] = fmul float [[ADD_1]], 0.000000e+00
; CHECK-NEXT: store float [[MUL_1]], ptr [[GEP_3]], align 4
; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i8, ptr [[GEP_1]], i64 4
; CHECK-NEXT: [[L_3:%.*]] = load float, ptr [[GEP_4]], align 4
; CHECK-NEXT: [[GEP_5:%.*]] = getelementptr inbounds i8, ptr [[GEP_2]], i64 4
; CHECK-NEXT: [[L_4:%.*]] = load float, ptr [[GEP_5]], align 4
; CHECK-NEXT: [[ADD_2:%.*]] = fadd float [[L_3]], [[L_4]]
; CHECK-NEXT: [[MUL_2:%.*]] = fmul float [[ADD_2]], 0.000000e+00
; CHECK-NEXT: [[GEP_6:%.*]] = getelementptr inbounds i8, ptr [[GEP_3]], i64 4
; CHECK-NEXT: store float [[MUL_2]], ptr [[GEP_6]], align 4
; CHECK-NEXT: [[GEP_7:%.*]] = getelementptr inbounds i8, ptr [[GEP_1]], i64 8
; CHECK-NEXT: [[L_5:%.*]] = load float, ptr [[GEP_7]], align 4
; CHECK-NEXT: [[GEP_8:%.*]] = getelementptr inbounds i8, ptr [[GEP_2]], i64 8
; CHECK-NEXT: [[L_6:%.*]] = load float, ptr [[GEP_8]], align 4
; CHECK-NEXT: [[ADD_3:%.*]] = fadd float [[L_5]], [[L_6]]
; CHECK-NEXT: [[MUL_3:%.*]] = fmul float [[ADD_3]], 0.000000e+00
; CHECK-NEXT: [[GEP_9:%.*]] = getelementptr inbounds i8, ptr [[GEP_3]], i64 8
; CHECK-NEXT: store float [[MUL_3]], ptr [[GEP_9]], align 4
; CHECK-NEXT: [[I27:%.*]] = getelementptr inbounds i8, ptr [[GEP_1]], i64 12
; CHECK-NEXT: [[L_7:%.*]] = load float, ptr [[I27]], align 4
; CHECK-NEXT: [[GEP_10:%.*]] = getelementptr inbounds i8, ptr [[GEP_2]], i64 12
; CHECK-NEXT: [[L_8:%.*]] = load float, ptr [[GEP_10]], align 4
; CHECK-NEXT: [[ADD_4:%.*]] = fadd float [[L_7]], [[L_8]]
; CHECK-NEXT: [[MUL_4:%.*]] = fmul float [[ADD_4]], 0.000000e+00
; CHECK-NEXT: [[GEP_11:%.*]] = getelementptr inbounds i8, ptr [[GEP_3]], i64 12
; CHECK-NEXT: store float [[MUL_4]], ptr [[GEP_11]], align 4
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[ARG1]]
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%shl.iv.5 = shl i64 %iv, 5
%gep.1 = getelementptr inbounds i8, ptr %arg, i64 %shl.iv.5
%add.5 = or disjoint i64 %shl.iv.5, 16
%gep.2 = getelementptr i8, ptr %arg, i64 %add.5
%shl.iv.4 = shl i64 %iv, 4
%gep.3 = getelementptr inbounds i8, ptr %arg2, i64 %shl.iv.4
%l.1 = load float, ptr %gep.1, align 4
%l.2 = load float, ptr %gep.2, align 4
%add.1 = fadd float %l.1, %l.2
%mul.1 = fmul float %add.1, 0.000000e+00
store float %mul.1, ptr %gep.3, align 4
%gep.4 = getelementptr inbounds i8, ptr %gep.1, i64 4
%l.3 = load float, ptr %gep.4, align 4
%gep.5 = getelementptr inbounds i8, ptr %gep.2, i64 4
%l.4 = load float, ptr %gep.5, align 4
%add.2 = fadd float %l.3, %l.4
%mul.2 = fmul float %add.2, 0.000000e+00
%gep.6 = getelementptr inbounds i8, ptr %gep.3, i64 4
store float %mul.2, ptr %gep.6, align 4
%gep.7 = getelementptr inbounds i8, ptr %gep.1, i64 8
%l.5 = load float, ptr %gep.7, align 4
%gep.8 = getelementptr inbounds i8, ptr %gep.2, i64 8
%l.6 = load float, ptr %gep.8, align 4
%add.3 = fadd float %l.5, %l.6
%mul.3 = fmul float %add.3, 0.000000e+00
%gep.9 = getelementptr inbounds i8, ptr %gep.3, i64 8
store float %mul.3, ptr %gep.9, align 4
%i27 = getelementptr inbounds i8, ptr %gep.1, i64 12
%l.7 = load float, ptr %i27, align 4
%gep.10 = getelementptr inbounds i8, ptr %gep.2, i64 12
%l.8 = load float, ptr %gep.10, align 4
%add.4 = fadd float %l.7, %l.8
%mul.4 = fmul float %add.4, 0.000000e+00
%gep.11 = getelementptr inbounds i8, ptr %gep.3, i64 12
store float %mul.4, ptr %gep.11, align 4
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv, %arg1
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @geps_feeding_interleave_groups_with_reuse2(ptr %A, ptr %B, i64 %N) #1 {
; CHECK-LABEL: define void @geps_feeding_interleave_groups_with_reuse2(
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[N]], 3
; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 28
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[N]], 3
; CHECK-NEXT: [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i64, i1 } [[MUL]], 0
; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[A]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[A]]
; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP4]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[TMP6]], [[SCEVGEP]]
; CHECK-NEXT: [[TMP8:%.*]] = or i1 [[TMP7]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP4:%.*]] = getelementptr i8, ptr [[A]], i64 8
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[SCEVGEP4]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[SCEVGEP4]]
; CHECK-NEXT: [[TMP11:%.*]] = or i1 [[TMP10]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP8:%.*]] = getelementptr i8, ptr [[A]], i64 12
; CHECK-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[SCEVGEP8]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[TMP12]], [[SCEVGEP8]]
; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP13]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP12:%.*]] = getelementptr i8, ptr [[A]], i64 16
; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[SCEVGEP12]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP16:%.*]] = icmp ult ptr [[TMP15]], [[SCEVGEP12]]
; CHECK-NEXT: [[TMP17:%.*]] = or i1 [[TMP16]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP16:%.*]] = getelementptr i8, ptr [[A]], i64 20
; CHECK-NEXT: [[TMP18:%.*]] = getelementptr i8, ptr [[SCEVGEP16]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP19:%.*]] = icmp ult ptr [[TMP18]], [[SCEVGEP16]]
; CHECK-NEXT: [[TMP20:%.*]] = or i1 [[TMP19]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP20:%.*]] = getelementptr i8, ptr [[A]], i64 24
; CHECK-NEXT: [[TMP21:%.*]] = getelementptr i8, ptr [[SCEVGEP20]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP22:%.*]] = icmp ult ptr [[TMP21]], [[SCEVGEP20]]
; CHECK-NEXT: [[TMP23:%.*]] = or i1 [[TMP22]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP24:%.*]] = getelementptr i8, ptr [[A]], i64 28
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[SCEVGEP24]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP25:%.*]] = icmp ult ptr [[TMP24]], [[SCEVGEP24]]
; CHECK-NEXT: [[TMP26:%.*]] = or i1 [[TMP25]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[SCEVGEP28:%.*]] = getelementptr i8, ptr [[B]], i64 4
; CHECK-NEXT: [[MUL29:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 [[TMP2]])
; CHECK-NEXT: [[MUL_RESULT30:%.*]] = extractvalue { i64, i1 } [[MUL29]], 0
; CHECK-NEXT: [[MUL_OVERFLOW31:%.*]] = extractvalue { i64, i1 } [[MUL29]], 1
; CHECK-NEXT: [[TMP27:%.*]] = getelementptr i8, ptr [[SCEVGEP28]], i64 [[MUL_RESULT30]]
; CHECK-NEXT: [[TMP28:%.*]] = icmp ult ptr [[TMP27]], [[SCEVGEP28]]
; CHECK-NEXT: [[TMP29:%.*]] = or i1 [[TMP28]], [[MUL_OVERFLOW31]]
; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[B]], i64 [[MUL_RESULT]]
; CHECK-NEXT: [[TMP31:%.*]] = icmp ult ptr [[TMP30]], [[B]]
; CHECK-NEXT: [[TMP32:%.*]] = or i1 [[TMP31]], [[MUL_OVERFLOW]]
; CHECK-NEXT: [[TMP33:%.*]] = or i1 [[TMP5]], [[TMP8]]
; CHECK-NEXT: [[TMP34:%.*]] = or i1 [[TMP33]], [[TMP11]]
; CHECK-NEXT: [[TMP35:%.*]] = or i1 [[TMP34]], [[TMP14]]
; CHECK-NEXT: [[TMP36:%.*]] = or i1 [[TMP35]], [[TMP17]]
; CHECK-NEXT: [[TMP37:%.*]] = or i1 [[TMP36]], [[TMP20]]
; CHECK-NEXT: [[TMP38:%.*]] = or i1 [[TMP37]], [[TMP23]]
; CHECK-NEXT: [[TMP39:%.*]] = or i1 [[TMP38]], [[TMP26]]
; CHECK-NEXT: [[TMP40:%.*]] = or i1 [[TMP39]], [[TMP29]]
; CHECK-NEXT: [[TMP41:%.*]] = or i1 [[TMP40]], [[TMP32]]
; CHECK-NEXT: br i1 [[TMP41]], label %[[SCALAR_PH]], label %[[VECTOR_MEMCHECK:.*]]
; CHECK: [[VECTOR_MEMCHECK]]:
; CHECK-NEXT: [[TMP42:%.*]] = lshr i64 [[N]], 3
; CHECK-NEXT: [[TMP43:%.*]] = shl i64 [[TMP42]], 5
; CHECK-NEXT: [[TMP44:%.*]] = add nuw nsw i64 [[TMP43]], 4
; CHECK-NEXT: [[SCEVGEP35:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP44]]
; CHECK-NEXT: [[TMP45:%.*]] = add i64 [[TMP43]], 32
; CHECK-NEXT: [[SCEVGEP36:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP45]]
; CHECK-NEXT: [[TMP46:%.*]] = shl i64 [[TMP42]], 4
; CHECK-NEXT: [[TMP47:%.*]] = add nuw nsw i64 [[TMP46]], 8
; CHECK-NEXT: [[SCEVGEP37:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP47]]
; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[B]], [[SCEVGEP36]]
; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[A]], [[SCEVGEP35]]
; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
; CHECK-NEXT: [[BOUND038:%.*]] = icmp ult ptr [[B]], [[SCEVGEP36]]
; CHECK-NEXT: [[BOUND139:%.*]] = icmp ult ptr [[A]], [[SCEVGEP37]]
; CHECK-NEXT: [[FOUND_CONFLICT40:%.*]] = and i1 [[BOUND038]], [[BOUND139]]
; CHECK-NEXT: [[CONFLICT_RDX:%.*]] = or i1 [[FOUND_CONFLICT]], [[FOUND_CONFLICT40]]
; CHECK-NEXT: br i1 [[CONFLICT_RDX]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP1]], 3
; CHECK-NEXT: [[TMP48:%.*]] = icmp eq i64 [[N_MOD_VF]], 0
; CHECK-NEXT: [[TMP49:%.*]] = select i1 [[TMP48]], i64 4, i64 [[N_MOD_VF]]
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP49]]
; CHECK-NEXT: [[TMP50:%.*]] = shl i64 [[N_VEC]], 3
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 0, i64 8, i64 16, i64 24>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP51:%.*]] = shl nuw i64 [[INDEX]], 3
; CHECK-NEXT: [[TMP52:%.*]] = lshr exact i64 [[TMP51]], 1
; CHECK-NEXT: [[TMP53:%.*]] = getelementptr nusw i32, ptr [[B]], i64 [[TMP52]]
; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <16 x i32>, ptr [[TMP53]], align 4, !alias.scope [[META3:![0-9]+]], !noalias [[META6:![0-9]+]]
; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <16 x i32> [[WIDE_VEC]], <16 x i32> poison, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
; CHECK-NEXT: [[STRIDED_VEC41:%.*]] = shufflevector <16 x i32> [[WIDE_VEC]], <16 x i32> poison, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
; CHECK-NEXT: [[WIDE_GEP:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[VEC_IND]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[STRIDED_VEC]], <4 x ptr> align 4 [[WIDE_GEP]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP54:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 1)
; CHECK-NEXT: [[WIDE_GEP42:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP54]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> zeroinitializer, <4 x ptr> align 4 [[WIDE_GEP42]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP55:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 2)
; CHECK-NEXT: [[WIDE_GEP43:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP55]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[STRIDED_VEC41]], <4 x ptr> align 4 [[WIDE_GEP43]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP56:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 3)
; CHECK-NEXT: [[WIDE_GEP44:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP56]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> zeroinitializer, <4 x ptr> align 4 [[WIDE_GEP44]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP57:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 4)
; CHECK-NEXT: [[WIDE_GEP45:%.*]] = getelementptr i32, ptr [[B]], <4 x i64> [[VEC_IND]]
; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> align 4 [[WIDE_GEP45]], <4 x i1> splat (i1 true), <4 x i32> poison), !alias.scope [[META8:![0-9]+]], !noalias [[META6]]
; CHECK-NEXT: [[WIDE_GEP46:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP57]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[WIDE_MASKED_GATHER]], <4 x ptr> align 4 [[WIDE_GEP46]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP58:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 5)
; CHECK-NEXT: [[WIDE_GEP47:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP58]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> zeroinitializer, <4 x ptr> align 4 [[WIDE_GEP47]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP59:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 6)
; CHECK-NEXT: [[WIDE_GEP48:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP59]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> zeroinitializer, <4 x ptr> align 4 [[WIDE_GEP48]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[TMP60:%.*]] = or disjoint <4 x i64> [[VEC_IND]], splat (i64 7)
; CHECK-NEXT: [[WIDE_GEP49:%.*]] = getelementptr i32, ptr [[A]], <4 x i64> [[TMP60]]
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> zeroinitializer, <4 x ptr> align 4 [[WIDE_GEP49]], <4 x i1> splat (i1 true)), !alias.scope [[META6]]
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <4 x i64> [[VEC_IND]], splat (i64 32)
; CHECK-NEXT: [[TMP61:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP61]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[SCALAR_PH]]
; CHECK: [[SCALAR_PH]]:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP50]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ], [ 0, %[[VECTOR_SCEVCHECK]] ], [ 0, %[[VECTOR_MEMCHECK]] ]
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT_7:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[SHR_1:%.*]] = lshr exact i64 [[IV]], 1
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr nusw i32, ptr [[B]], i64 [[SHR_1]]
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP_B]], align 4
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
; CHECK-NEXT: store i32 [[L]], ptr [[GEP_A]], align 4
; CHECK-NEXT: [[IV_NEXT:%.*]] = or disjoint i64 [[IV]], 1
; CHECK-NEXT: [[GEP_A_1:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT]]
; CHECK-NEXT: store i32 0, ptr [[GEP_A_1]], align 4
; CHECK-NEXT: [[IV_NEXT_1:%.*]] = or disjoint i64 [[IV]], 2
; CHECK-NEXT: [[SHR_2:%.*]] = lshr exact i64 [[IV_NEXT_1]], 1
; CHECK-NEXT: [[GEP_B_2:%.*]] = getelementptr i32, ptr [[B]], i64 [[SHR_2]]
; CHECK-NEXT: [[TMP62:%.*]] = load i32, ptr [[GEP_B_2]], align 4
; CHECK-NEXT: [[GEP_A_2:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_1]]
; CHECK-NEXT: store i32 [[TMP62]], ptr [[GEP_A_2]], align 4
; CHECK-NEXT: [[IV_NEXT_2:%.*]] = or disjoint i64 [[IV]], 3
; CHECK-NEXT: [[GEP_A_3:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_2]]
; CHECK-NEXT: store i32 0, ptr [[GEP_A_3]], align 4
; CHECK-NEXT: [[IV_NEXT_3:%.*]] = or disjoint i64 [[IV]], 4
; CHECK-NEXT: [[GEP_B_4:%.*]] = getelementptr i32, ptr [[B]], i64 [[IV]]
; CHECK-NEXT: [[TMP63:%.*]] = load i32, ptr [[GEP_B_4]], align 4
; CHECK-NEXT: [[GEP_A_4:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_3]]
; CHECK-NEXT: store i32 [[TMP63]], ptr [[GEP_A_4]], align 4
; CHECK-NEXT: [[IV_NEXT_4:%.*]] = or disjoint i64 [[IV]], 5
; CHECK-NEXT: [[GEP_A_5:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_4]]
; CHECK-NEXT: store i32 0, ptr [[GEP_A_5]], align 4
; CHECK-NEXT: [[IV_NEXT_5:%.*]] = or disjoint i64 [[IV]], 6
; CHECK-NEXT: [[GEP_A_6:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_5]]
; CHECK-NEXT: store i32 0, ptr [[GEP_A_6]], align 4
; CHECK-NEXT: [[IV_NEXT_6:%.*]] = or disjoint i64 [[IV]], 7
; CHECK-NEXT: [[GEP_A_7:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_6]]
; CHECK-NEXT: store i32 0, ptr [[GEP_A_7]], align 4
; CHECK-NEXT: [[IV_NEXT_7]] = add nuw nsw i64 [[IV]], 8
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[N]]
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP11:![0-9]+]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next.7, %loop ]
%shr.1 = lshr exact i64 %iv, 1
%gep.B = getelementptr nusw i32, ptr %B, i64 %shr.1
%l = load i32, ptr %gep.B, align 4
%gep.A = getelementptr i32, ptr %A, i64 %iv
store i32 %l, ptr %gep.A, align 4
%iv.next = or disjoint i64 %iv, 1
%gep.A.1 = getelementptr i32, ptr %A, i64 %iv.next
store i32 0, ptr %gep.A.1, align 4
%iv.next.1 = or disjoint i64 %iv, 2
%shr.2 = lshr exact i64 %iv.next.1, 1
%gep.B.2 = getelementptr i32, ptr %B, i64 %shr.2
%1 = load i32, ptr %gep.B.2, align 4
%gep.A.2 = getelementptr i32, ptr %A, i64 %iv.next.1
store i32 %1, ptr %gep.A.2, align 4
%iv.next.2 = or disjoint i64 %iv, 3
%gep.A.3 = getelementptr i32, ptr %A, i64 %iv.next.2
store i32 0, ptr %gep.A.3, align 4
%iv.next.3 = or disjoint i64 %iv, 4
%gep.B.4 = getelementptr i32, ptr %B, i64 %iv
%2 = load i32, ptr %gep.B.4, align 4
%gep.A.4 = getelementptr i32, ptr %A, i64 %iv.next.3
store i32 %2, ptr %gep.A.4, align 4
%iv.next.4 = or disjoint i64 %iv, 5
%gep.A.5 = getelementptr i32, ptr %A, i64 %iv.next.4
store i32 0, ptr %gep.A.5, align 4
%iv.next.5 = or disjoint i64 %iv, 6
%gep.A.6 = getelementptr i32, ptr %A, i64 %iv.next.5
store i32 0, ptr %gep.A.6, align 4
%iv.next.6 = or disjoint i64 %iv, 7
%gep.A.7 = getelementptr i32, ptr %A, i64 %iv.next.6
store i32 0, ptr %gep.A.7, align 4
%iv.next.7 = add nuw nsw i64 %iv, 8
%ec = icmp eq i64 %iv, %N
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Test case for https://github.com/llvm/llvm-project/issues/112922.
define void @interleave_store_double_i64(ptr %dst) {
; CHECK-LABEL: define void @interleave_store_double_i64(
; CHECK-SAME: ptr [[DST:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: store <4 x double> <double 0.000000e+00, double 0.000000e+00, double 0.000000e+00, double 4.940660e-324>, ptr [[DST]], align 8
; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.1 = getelementptr { double, i64 }, ptr %dst, i64 %iv, i32 1
store i64 %iv, ptr %gep.1, align 8
%gep.0 = getelementptr { double, i64 }, ptr %dst, i64 %iv
store double 0.000000e+00, ptr %gep.0, align 8
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv, 1
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @interleave_store_i64_double(ptr %dst) {
; CHECK-LABEL: define void @interleave_store_i64_double(
; CHECK-SAME: ptr [[DST:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr { double, i64 }, ptr [[DST]], i64 [[IV]]
; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_0]], align 8
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr { double, i64 }, ptr [[DST]], i64 [[IV]], i32 1
; CHECK-NEXT: store i64 [[IV]], ptr [[GEP_1]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], 1
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.0 = getelementptr { double, i64 }, ptr %dst, i64 %iv
store double 0.000000e+00, ptr %gep.0, align 8
%gep.1 = getelementptr { double, i64 }, ptr %dst, i64 %iv, i32 1
store i64 %iv, ptr %gep.1, align 8
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv, 1
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; TODO: The interleave group should likely have the same cost as @interleave_store_double_i64.
define void @interleave_store_double_i64_2(ptr %dst) {
; CHECK-LABEL: define void @interleave_store_double_i64_2(
; CHECK-SAME: ptr [[DST:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr { i64, double }, ptr [[DST]], i64 [[IV]], i32 1
; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_1]], align 8
; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr { i64, double }, ptr [[DST]], i64 [[IV]]
; CHECK-NEXT: store i64 [[IV]], ptr [[GEP_0]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], 1
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.1 = getelementptr { i64, double }, ptr %dst, i64 %iv, i32 1
store double 0.000000e+00, ptr %gep.1, align 8
%gep.0 = getelementptr { i64, double }, ptr %dst, i64 %iv
store i64 %iv, ptr %gep.0, align 8
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv, 1
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @interleave_store_i64_double_2(ptr %dst) {
; CHECK-LABEL: define void @interleave_store_i64_double_2(
; CHECK-SAME: ptr [[DST:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: store <4 x double> <double 0.000000e+00, double 0.000000e+00, double 4.940660e-324, double 0.000000e+00>, ptr [[DST]], align 8
; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.0 = getelementptr { i64, double }, ptr %dst, i64 %iv
store i64 %iv, ptr %gep.0, align 8
%gep.1 = getelementptr { i64, double }, ptr %dst, i64 %iv, i32 1
store double 0.000000e+00, ptr %gep.1, align 8
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv, 1
br i1 %ec, label %exit, label %loop
exit:
ret void
}
attributes #0 = { "target-features"="+sse4.2" }
attributes #1 = { "min-legal-vector-width"="0" "target-cpu"="cascadelake" }
;.
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
; CHECK: [[META3]] = !{[[META4:![0-9]+]]}
; CHECK: [[META4]] = distinct !{[[META4]], [[META5:![0-9]+]]}
; CHECK: [[META5]] = distinct !{[[META5]], !"LVerDomain"}
; CHECK: [[META6]] = !{[[META7:![0-9]+]]}
; CHECK: [[META7]] = distinct !{[[META7]], [[META5]]}
; CHECK: [[META8]] = !{[[META9:![0-9]+]]}
; CHECK: [[META9]] = distinct !{[[META9]], [[META5]]}
; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]], [[META2]]}
; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META1]]}
;.