
Currently we only allow folding not (cmp eq) -> icmp ne if the not is the only user of the compare. However a common scenario is that some select might also use the compare. We can still fold the not if we also swizzle the arms of the selects. This helps avoid regressions in #150368
326 lines
17 KiB
LLVM
326 lines
17 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s | FileCheck %s
|
|
|
|
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
|
|
|
|
%struct.Foo = type { [32000 x i32], [32000 x i32] }
|
|
|
|
@foo = global %struct.Foo zeroinitializer, align 4
|
|
|
|
define void @accesses_to_struct_dereferenceable(ptr noalias %dst) {
|
|
; CHECK-LABEL: define void @accesses_to_struct_dereferenceable
|
|
; CHECK-SAME: (ptr noalias [[DST:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], 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:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <4 x i32> [[WIDE_LOAD]], zeroinitializer
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr @foo, i64 0, i32 1, i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i32>, ptr [[TMP3]], align 4
|
|
; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[WIDE_LOAD2]], <4 x i32> [[WIDE_LOAD1]]
|
|
; CHECK-NEXT: store <4 x i32> [[PREDPHI]], ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32000
|
|
; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
|
|
; CHECK: middle.block:
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: scalar.ph:
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]]
|
|
; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[D]], 0
|
|
; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: [[TMP_0:%.*]] = phi i32 [ [[L_A]], [[IF_THEN]] ], [ [[L_B]], [[IF_ELSE]] ]
|
|
; CHECK-NEXT: store i32 [[TMP_0]], ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 32000
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP3:![0-9]+]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
|
|
%gep.dst = getelementptr inbounds i32, ptr %dst, i64 %iv
|
|
%d = load i32, ptr %gep.dst, align 4
|
|
%cmp3 = icmp ult i32 %d, 0
|
|
br i1 %cmp3, label %if.then, label %if.else
|
|
|
|
if.then:
|
|
%gep.a = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 0, i64 %iv
|
|
%l.a = load i32, ptr %gep.a, align 4
|
|
br label %loop.latch
|
|
|
|
if.else:
|
|
%gep.b = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 1, i64 %iv
|
|
%l.b = load i32, ptr %gep.b, align 4
|
|
br label %loop.latch
|
|
|
|
loop.latch:
|
|
%tmp.0 = phi i32 [ %l.a, %if.then ], [ %l.b, %if.else ]
|
|
store i32 %tmp.0, ptr %gep.dst, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond.not = icmp eq i64 %iv.next, 32000
|
|
br i1 %exitcond.not, label %exit, label %loop.header
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @accesses_to_struct_may_not_be_dereferenceable_due_to_loop_bound(ptr noalias %dst) {
|
|
; CHECK-LABEL: define void @accesses_to_struct_may_not_be_dereferenceable_due_to_loop_bound
|
|
; CHECK-SAME: (ptr noalias [[DST:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], 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:%.*]], [[PRED_LOAD_CONTINUE6:%.*]] ]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp uge <4 x i32> [[WIDE_LOAD]], zeroinitializer
|
|
; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]]
|
|
; CHECK: pred.load.if:
|
|
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0
|
|
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr @foo, i64 0, i32 1, i64 [[TMP3]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
|
|
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> poison, i32 [[TMP5]], i32 0
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE]]
|
|
; CHECK: pred.load.continue:
|
|
; CHECK-NEXT: [[TMP7:%.*]] = phi <4 x i32> [ poison, [[VECTOR_BODY]] ], [ [[TMP6]], [[PRED_LOAD_IF]] ]
|
|
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1
|
|
; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_LOAD_IF1:%.*]], label [[PRED_LOAD_CONTINUE2:%.*]]
|
|
; CHECK: pred.load.if1:
|
|
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 1
|
|
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP9]]
|
|
; CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
|
|
; CHECK-NEXT: [[TMP12:%.*]] = insertelement <4 x i32> [[TMP7]], i32 [[TMP11]], i32 1
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE2]]
|
|
; CHECK: pred.load.continue2:
|
|
; CHECK-NEXT: [[TMP13:%.*]] = phi <4 x i32> [ [[TMP7]], [[PRED_LOAD_CONTINUE]] ], [ [[TMP12]], [[PRED_LOAD_IF1]] ]
|
|
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2
|
|
; CHECK-NEXT: br i1 [[TMP14]], label [[PRED_LOAD_IF3:%.*]], label [[PRED_LOAD_CONTINUE4:%.*]]
|
|
; CHECK: pred.load.if3:
|
|
; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 2
|
|
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP15]]
|
|
; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
|
|
; CHECK-NEXT: [[TMP18:%.*]] = insertelement <4 x i32> [[TMP13]], i32 [[TMP17]], i32 2
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE4]]
|
|
; CHECK: pred.load.continue4:
|
|
; CHECK-NEXT: [[TMP19:%.*]] = phi <4 x i32> [ [[TMP13]], [[PRED_LOAD_CONTINUE2]] ], [ [[TMP18]], [[PRED_LOAD_IF3]] ]
|
|
; CHECK-NEXT: [[TMP20:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3
|
|
; CHECK-NEXT: br i1 [[TMP20]], label [[PRED_LOAD_IF5:%.*]], label [[PRED_LOAD_CONTINUE6]]
|
|
; CHECK: pred.load.if5:
|
|
; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[INDEX]], 3
|
|
; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP21]]
|
|
; CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
|
|
; CHECK-NEXT: [[TMP24:%.*]] = insertelement <4 x i32> [[TMP19]], i32 [[TMP23]], i32 3
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE6]]
|
|
; CHECK: pred.load.continue6:
|
|
; CHECK-NEXT: [[TMP25:%.*]] = phi <4 x i32> [ [[TMP19]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP24]], [[PRED_LOAD_IF5]] ]
|
|
; CHECK-NEXT: [[TMP26:%.*]] = getelementptr [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD7:%.*]] = load <4 x i32>, ptr [[TMP26]], align 4
|
|
; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[TMP25]], <4 x i32> [[WIDE_LOAD7]]
|
|
; CHECK-NEXT: store <4 x i32> [[PREDPHI]], ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
|
|
; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32000
|
|
; CHECK-NEXT: br i1 [[TMP27]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
|
|
; CHECK: middle.block:
|
|
; CHECK-NEXT: br label [[SCALAR_PH]]
|
|
; CHECK: scalar.ph:
|
|
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 32000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]]
|
|
; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[D]], 0
|
|
; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: [[TMP_0:%.*]] = phi i32 [ [[L_A]], [[IF_THEN]] ], [ [[L_B]], [[IF_ELSE]] ]
|
|
; CHECK-NEXT: store i32 [[TMP_0]], ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 32001
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP5:![0-9]+]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
|
|
%gep.dst = getelementptr inbounds i32, ptr %dst, i64 %iv
|
|
%d = load i32, ptr %gep.dst, align 4
|
|
%cmp3 = icmp ult i32 %d, 0
|
|
br i1 %cmp3, label %if.then, label %if.else
|
|
|
|
if.then:
|
|
%gep.a = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 0, i64 %iv
|
|
%l.a = load i32, ptr %gep.a, align 4
|
|
br label %loop.latch
|
|
|
|
if.else:
|
|
%gep.b = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 1, i64 %iv
|
|
%l.b = load i32, ptr %gep.b, align 4
|
|
br label %loop.latch
|
|
|
|
loop.latch:
|
|
%tmp.0 = phi i32 [ %l.a, %if.then ], [ %l.b, %if.else ]
|
|
store i32 %tmp.0, ptr %gep.dst, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond.not = icmp eq i64 %iv.next, 32001
|
|
br i1 %exitcond.not, label %exit, label %loop.header
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @accesses_to_struct_may_not_be_dereferenceable_access_size(ptr noalias %dst) {
|
|
; CHECK-LABEL: define void @accesses_to_struct_may_not_be_dereferenceable_access_size
|
|
; CHECK-SAME: (ptr noalias [[DST:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], 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:%.*]], [[PRED_LOAD_CONTINUE6:%.*]] ]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp uge <4 x i32> [[WIDE_LOAD]], zeroinitializer
|
|
; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]]
|
|
; CHECK: pred.load.if:
|
|
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0
|
|
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr @foo, i64 0, i32 1, i64 [[TMP3]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 4
|
|
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i64> poison, i64 [[TMP5]], i32 0
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE]]
|
|
; CHECK: pred.load.continue:
|
|
; CHECK-NEXT: [[TMP7:%.*]] = phi <4 x i64> [ poison, [[VECTOR_BODY]] ], [ [[TMP6]], [[PRED_LOAD_IF]] ]
|
|
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1
|
|
; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_LOAD_IF1:%.*]], label [[PRED_LOAD_CONTINUE2:%.*]]
|
|
; CHECK: pred.load.if1:
|
|
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 1
|
|
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP9]]
|
|
; CHECK-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 4
|
|
; CHECK-NEXT: [[TMP12:%.*]] = insertelement <4 x i64> [[TMP7]], i64 [[TMP11]], i32 1
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE2]]
|
|
; CHECK: pred.load.continue2:
|
|
; CHECK-NEXT: [[TMP13:%.*]] = phi <4 x i64> [ [[TMP7]], [[PRED_LOAD_CONTINUE]] ], [ [[TMP12]], [[PRED_LOAD_IF1]] ]
|
|
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2
|
|
; CHECK-NEXT: br i1 [[TMP14]], label [[PRED_LOAD_IF3:%.*]], label [[PRED_LOAD_CONTINUE4:%.*]]
|
|
; CHECK: pred.load.if3:
|
|
; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 2
|
|
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP15]]
|
|
; CHECK-NEXT: [[TMP17:%.*]] = load i64, ptr [[TMP16]], align 4
|
|
; CHECK-NEXT: [[TMP18:%.*]] = insertelement <4 x i64> [[TMP13]], i64 [[TMP17]], i32 2
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE4]]
|
|
; CHECK: pred.load.continue4:
|
|
; CHECK-NEXT: [[TMP19:%.*]] = phi <4 x i64> [ [[TMP13]], [[PRED_LOAD_CONTINUE2]] ], [ [[TMP18]], [[PRED_LOAD_IF3]] ]
|
|
; CHECK-NEXT: [[TMP20:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3
|
|
; CHECK-NEXT: br i1 [[TMP20]], label [[PRED_LOAD_IF5:%.*]], label [[PRED_LOAD_CONTINUE6]]
|
|
; CHECK: pred.load.if5:
|
|
; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[INDEX]], 3
|
|
; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[TMP21]]
|
|
; CHECK-NEXT: [[TMP23:%.*]] = load i64, ptr [[TMP22]], align 4
|
|
; CHECK-NEXT: [[TMP24:%.*]] = insertelement <4 x i64> [[TMP19]], i64 [[TMP23]], i32 3
|
|
; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE6]]
|
|
; CHECK: pred.load.continue6:
|
|
; CHECK-NEXT: [[TMP25:%.*]] = phi <4 x i64> [ [[TMP19]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP24]], [[PRED_LOAD_IF5]] ]
|
|
; CHECK-NEXT: [[TMP26:%.*]] = trunc <4 x i64> [[TMP25]] to <4 x i32>
|
|
; CHECK-NEXT: [[TMP27:%.*]] = getelementptr [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[INDEX]]
|
|
; CHECK-NEXT: [[WIDE_LOAD7:%.*]] = load <4 x i32>, ptr [[TMP27]], align 4
|
|
; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[TMP26]], <4 x i32> [[WIDE_LOAD7]]
|
|
; CHECK-NEXT: store <4 x i32> [[PREDPHI]], ptr [[TMP0]], align 4
|
|
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
|
|
; CHECK-NEXT: [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32000
|
|
; CHECK-NEXT: br i1 [[TMP28]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
|
|
; CHECK: middle.block:
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: scalar.ph:
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]]
|
|
; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[D]], 0
|
|
; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 0, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @foo, i64 0, i32 1, i64 [[IV]]
|
|
; CHECK-NEXT: [[L_B:%.*]] = load i64, ptr [[GEP_B]], align 4
|
|
; CHECK-NEXT: [[T:%.*]] = trunc i64 [[L_B]] to i32
|
|
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: [[TMP_0:%.*]] = phi i32 [ [[L_A]], [[IF_THEN]] ], [ [[T]], [[IF_ELSE]] ]
|
|
; CHECK-NEXT: store i32 [[TMP_0]], ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 32000
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
|
|
%gep.dst = getelementptr inbounds i32, ptr %dst, i64 %iv
|
|
%d = load i32, ptr %gep.dst, align 4
|
|
%cmp3 = icmp ult i32 %d, 0
|
|
br i1 %cmp3, label %if.then, label %if.else
|
|
|
|
if.then:
|
|
%gep.a = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 0, i64 %iv
|
|
%l.a = load i32, ptr %gep.a, align 4
|
|
br label %loop.latch
|
|
|
|
if.else:
|
|
%gep.b = getelementptr inbounds %struct.Foo, ptr @foo, i64 0, i32 1, i64 %iv
|
|
%l.b = load i64, ptr %gep.b, align 4
|
|
%t = trunc i64 %l.b to i32
|
|
br label %loop.latch
|
|
|
|
loop.latch:
|
|
%tmp.0 = phi i32 [ %l.a, %if.then ], [ %t, %if.else ]
|
|
store i32 %tmp.0, ptr %gep.dst, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond.not = icmp eq i64 %iv.next, 32000
|
|
br i1 %exitcond.not, label %exit, label %loop.header
|
|
|
|
exit:
|
|
ret void
|
|
}
|