Skip to content

Commit 22637a8

Browse files
authored
[Loads] Respect UseDerefAtPointSemantics in isDerefAndAlignedPointer. (#123196)
If a pointer gets freed, it may not be dereferenceable any longer, even though there is a dominating dereferenceable assumption. As first step, only consider assumptions if the pointer value cannot be freed if UseDerefAtPointSemantics is used. PR: #123196
1 parent 8a229f5 commit 22637a8

File tree

3 files changed

+138
-24
lines changed

3 files changed

+138
-24
lines changed

Diff for: llvm/lib/Analysis/Loads.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
using namespace llvm;
2727

28+
extern cl::opt<bool> UseDerefAtPointSemantics;
29+
2830
static bool isAligned(const Value *Base, Align Alignment,
2931
const DataLayout &DL) {
3032
return Base->getPointerAlignment(DL) >= Alignment;
@@ -168,7 +170,7 @@ static bool isDereferenceableAndAlignedPointer(
168170
Size, DL, CtxI, AC, DT, TLI,
169171
Visited, MaxDepth);
170172

171-
if (CtxI) {
173+
if (CtxI && (!UseDerefAtPointSemantics || !V->canBeFreed())) {
172174
/// Look through assumes to see if both dereferencability and alignment can
173175
/// be proven by an assume if needed.
174176
RetainedKnowledge AlignRK;

Diff for: llvm/lib/IR/Value.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
using namespace llvm;
3838

39-
static cl::opt<bool> UseDerefAtPointSemantics(
39+
cl::opt<bool> UseDerefAtPointSemantics(
4040
"use-dereferenceable-at-point-semantics", cl::Hidden, cl::init(false),
4141
cl::desc("Deref attributes and metadata infer facts at definition only"));
4242

Diff for: llvm/test/Transforms/LoopVectorize/dereferenceable-info-from-assumption-constant-size.ll

+134-22
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2-
; RUN: opt -p loop-vectorize -force-vector-width=2 -use-dereferenceable-at-point-semantics=1 -S %s | FileCheck %s
2+
; RUN: opt -p loop-vectorize -force-vector-width=2 -use-dereferenceable-at-point-semantics -S %s | FileCheck %s
33

44
declare void @llvm.assume(i1)
55

6-
define void @deref_assumption_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
6+
define void @deref_assumption_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
77
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count(
88
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1:[0-9]+]] {
99
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -104,7 +104,7 @@ exit:
104104
ret void
105105
}
106106

107-
define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
107+
define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
108108
; CHECK-LABEL: define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
109109
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
110110
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -181,7 +181,7 @@ exit:
181181
ret void
182182
}
183183

184-
define void @deref_assumption_too_small_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
184+
define void @deref_assumption_too_small_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
185185
; CHECK-LABEL: define void @deref_assumption_too_small_in_header_constant_trip_count(
186186
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
187187
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -282,7 +282,7 @@ exit:
282282
ret void
283283
}
284284

285-
define void @deref_assumption_in_header_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
285+
define void @deref_assumption_in_header_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
286286
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_1(
287287
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
288288
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -383,7 +383,7 @@ exit:
383383
ret void
384384
}
385385

386-
define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree {
386+
define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{
387387
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(
388388
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
389389
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -484,7 +484,7 @@ exit:
484484
ret void
485485
}
486486

487-
define void @deref_assumption_in_header_constant_trip_count_align_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
487+
define void @deref_assumption_in_header_constant_trip_count_align_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
488488
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_not_known(
489489
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
490490
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -585,7 +585,7 @@ exit:
585585
ret void
586586
}
587587

588-
define void @deref_assumption_in_then_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
588+
define void @deref_assumption_in_then_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
589589
; CHECK-LABEL: define void @deref_assumption_in_then_constant_trip_count(
590590
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
591591
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -682,7 +682,7 @@ exit:
682682
ret void
683683
}
684684

685-
define void @deref_assumption_in_latch_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
685+
define void @deref_assumption_in_latch_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
686686
; CHECK-LABEL: define void @deref_assumption_in_latch_constant_trip_count(
687687
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
688688
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -785,7 +785,7 @@ exit:
785785
ret void
786786
}
787787

788-
define void @deref_assumption_in_header_variable_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) nofree {
788+
define void @deref_assumption_in_header_variable_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) nofree nosync{
789789
; CHECK-LABEL: define void @deref_assumption_in_header_variable_trip_count(
790790
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {
791791
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -890,7 +890,7 @@ exit:
890890
ret void
891891
}
892892

893-
define void @deref_assumption_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
893+
define void @deref_assumption_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
894894
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_1(
895895
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
896896
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -968,7 +968,7 @@ exit:
968968
ret void
969969
}
970970

971-
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
971+
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
972972
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(
973973
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
974974
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1063,7 +1063,7 @@ exit:
10631063
ret void
10641064
}
10651065

1066-
define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
1066+
define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
10671067
; CHECK-LABEL: define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(
10681068
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
10691069
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1142,7 +1142,7 @@ exit:
11421142
}
11431143

11441144

1145-
define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree {
1145+
define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{
11461146
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(
11471147
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
11481148
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1220,7 +1220,7 @@ exit:
12201220
ret void
12211221
}
12221222

1223-
define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
1223+
define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
12241224
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(
12251225
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
12261226
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1315,7 +1315,7 @@ exit:
13151315
ret void
13161316
}
13171317

1318-
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree {
1318+
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
13191319
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(
13201320
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
13211321
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1410,8 +1410,8 @@ exit:
14101410
ret void
14111411
}
14121412

1413-
; %a may be freeed between the dereferenceable assumption and accesses.
1414-
; FIXME: It is not safe to use with -use-dereferenceable-at-point-semantics.
1413+
; %a may be freed between the dereferenceable assumption and accesses.
1414+
; It is not safe to use with -use-dereferenceable-at-point-semantics.
14151415
define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) {
14161416
; CHECK-LABEL: define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
14171417
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) {
@@ -1422,16 +1422,29 @@ define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_
14221422
; CHECK: [[VECTOR_PH]]:
14231423
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
14241424
; CHECK: [[VECTOR_BODY]]:
1425-
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
1425+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
14261426
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
14271427
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
14281428
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
14291429
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
14301430
; CHECK-NEXT: [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1431-
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
1431+
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1432+
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1433+
; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1434+
; CHECK: [[PRED_LOAD_IF]]:
14321435
; CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[A]], align 4
1433-
; CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x i32> poison, i32 [[TMP5]], i32 0
1434-
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP13]], i32 [[TMP15]], i32 1
1436+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP15]], i32 0
1437+
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]
1438+
; CHECK: [[PRED_LOAD_CONTINUE]]:
1439+
; CHECK-NEXT: [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ]
1440+
; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1441+
; CHECK-NEXT: br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1442+
; CHECK: [[PRED_LOAD_IF1]]:
1443+
; CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[A]], align 4
1444+
; CHECK-NEXT: [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP14]], i32 1
1445+
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]
1446+
; CHECK: [[PRED_LOAD_CONTINUE2]]:
1447+
; CHECK-NEXT: [[TMP11:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
14351448
; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP11]]
14361449
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
14371450
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0
@@ -1491,6 +1504,103 @@ exit:
14911504
ret void
14921505
}
14931506

1507+
; %a may be freed between the dereferenceable assumption and accesses.
1508+
; It is not safe to use with -use-dereferenceable-at-point-semantics.
1509+
define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %b, ptr noalias %c) nofree nosync {
1510+
; CHECK-LABEL: define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
1511+
; CHECK-SAME: ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1512+
; CHECK-NEXT: [[ENTRY:.*]]:
1513+
; CHECK-NEXT: [[A:%.*]] = call ptr @get_ptr()
1514+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4) ]
1515+
; CHECK-NEXT: call void @may_free()
1516+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1517+
; CHECK: [[VECTOR_PH]]:
1518+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
1519+
; CHECK: [[VECTOR_BODY]]:
1520+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
1521+
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
1522+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1523+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1524+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1525+
; CHECK-NEXT: [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1526+
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1527+
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1528+
; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1529+
; CHECK: [[PRED_LOAD_IF]]:
1530+
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[A]], align 4
1531+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP6]], i32 0
1532+
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]
1533+
; CHECK: [[PRED_LOAD_CONTINUE]]:
1534+
; CHECK-NEXT: [[TMP8:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ]
1535+
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1536+
; CHECK-NEXT: br i1 [[TMP9]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1537+
; CHECK: [[PRED_LOAD_IF1]]:
1538+
; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[A]], align 4
1539+
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP8]], i32 [[TMP10]], i32 1
1540+
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]
1541+
; CHECK: [[PRED_LOAD_CONTINUE2]]:
1542+
; CHECK-NEXT: [[TMP12:%.*]] = phi <2 x i32> [ [[TMP8]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP11]], %[[PRED_LOAD_IF1]] ]
1543+
; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP12]]
1544+
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1545+
; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i32 0
1546+
; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP14]], align 4
1547+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1548+
; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1549+
; CHECK-NEXT: br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP34:![0-9]+]]
1550+
; CHECK: [[MIDDLE_BLOCK]]:
1551+
; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1552+
; CHECK: [[SCALAR_PH]]:
1553+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1554+
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
1555+
; CHECK: [[LOOP_HEADER]]:
1556+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1557+
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1558+
; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1559+
; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1560+
; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1561+
; CHECK: [[LOOP_THEN]]:
1562+
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[A]], align 4
1563+
; CHECK-NEXT: br label %[[LOOP_LATCH]]
1564+
; CHECK: [[LOOP_LATCH]]:
1565+
; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1566+
; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1567+
; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 4
1568+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1569+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1570+
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP35:![0-9]+]]
1571+
; CHECK: [[EXIT]]:
1572+
; CHECK-NEXT: ret void
1573+
;
1574+
entry:
1575+
%a = call ptr @get_ptr()
1576+
call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ]
1577+
call void @may_free()
1578+
br label %loop.header
1579+
1580+
loop.header:
1581+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1582+
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1583+
%l.b = load i32, ptr %gep.b, align 4
1584+
%c.1 = icmp sge i32 %l.b, 0
1585+
br i1 %c.1, label %loop.latch, label %loop.then
1586+
1587+
loop.then:
1588+
%l.a = load i32, ptr %a, align 4
1589+
br label %loop.latch
1590+
1591+
loop.latch:
1592+
%merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1593+
%gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1594+
store i32 %merge, ptr %gep.c, align 4
1595+
%iv.next = add nuw nsw i64 %iv, 1
1596+
%ec = icmp eq i64 %iv.next, 1000
1597+
br i1 %ec, label %exit, label %loop.header
1598+
1599+
exit:
1600+
ret void
1601+
}
1602+
1603+
declare ptr @get_ptr()
14941604
declare void @may_free()
14951605

14961606
;.
@@ -1528,4 +1638,6 @@ declare void @may_free()
15281638
; CHECK: [[LOOP31]] = distinct !{[[LOOP31]], [[META2]], [[META1]]}
15291639
; CHECK: [[LOOP32]] = distinct !{[[LOOP32]], [[META1]], [[META2]]}
15301640
; CHECK: [[LOOP33]] = distinct !{[[LOOP33]], [[META2]], [[META1]]}
1641+
; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[META1]], [[META2]]}
1642+
; CHECK: [[LOOP35]] = distinct !{[[LOOP35]], [[META2]], [[META1]]}
15311643
;.

0 commit comments

Comments
 (0)