1
1
; 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
3
3
4
4
declare void @llvm.assume (i1 )
5
5
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 {
7
7
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count(
8
8
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1:[0-9]+]] {
9
9
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -104,7 +104,7 @@ exit:
104
104
ret void
105
105
}
106
106
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 {
108
108
; CHECK-LABEL: define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
109
109
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
110
110
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -181,7 +181,7 @@ exit:
181
181
ret void
182
182
}
183
183
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 {
185
185
; CHECK-LABEL: define void @deref_assumption_too_small_in_header_constant_trip_count(
186
186
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
187
187
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -282,7 +282,7 @@ exit:
282
282
ret void
283
283
}
284
284
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 {
286
286
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_1(
287
287
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
288
288
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -383,7 +383,7 @@ exit:
383
383
ret void
384
384
}
385
385
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 {
387
387
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(
388
388
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
389
389
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -484,7 +484,7 @@ exit:
484
484
ret void
485
485
}
486
486
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 {
488
488
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_not_known(
489
489
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
490
490
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -585,7 +585,7 @@ exit:
585
585
ret void
586
586
}
587
587
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 {
589
589
; CHECK-LABEL: define void @deref_assumption_in_then_constant_trip_count(
590
590
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
591
591
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -682,7 +682,7 @@ exit:
682
682
ret void
683
683
}
684
684
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 {
686
686
; CHECK-LABEL: define void @deref_assumption_in_latch_constant_trip_count(
687
687
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
688
688
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -785,7 +785,7 @@ exit:
785
785
ret void
786
786
}
787
787
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 {
789
789
; CHECK-LABEL: define void @deref_assumption_in_header_variable_trip_count(
790
790
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {
791
791
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -890,7 +890,7 @@ exit:
890
890
ret void
891
891
}
892
892
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 {
894
894
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_1(
895
895
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
896
896
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -968,7 +968,7 @@ exit:
968
968
ret void
969
969
}
970
970
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 {
972
972
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(
973
973
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
974
974
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1063,7 +1063,7 @@ exit:
1063
1063
ret void
1064
1064
}
1065
1065
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 {
1067
1067
; CHECK-LABEL: define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(
1068
1068
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1069
1069
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1142,7 +1142,7 @@ exit:
1142
1142
}
1143
1143
1144
1144
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 {
1146
1146
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(
1147
1147
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1148
1148
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1220,7 +1220,7 @@ exit:
1220
1220
ret void
1221
1221
}
1222
1222
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 {
1224
1224
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(
1225
1225
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1226
1226
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1315,7 +1315,7 @@ exit:
1315
1315
ret void
1316
1316
}
1317
1317
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 {
1319
1319
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(
1320
1320
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1321
1321
; CHECK-NEXT: [[ENTRY:.*]]:
@@ -1410,8 +1410,8 @@ exit:
1410
1410
ret void
1411
1411
}
1412
1412
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.
1415
1415
define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr (ptr noalias %a , ptr noalias %b , ptr noalias %c ) {
1416
1416
; CHECK-LABEL: define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
1417
1417
; 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_
1422
1422
; CHECK: [[VECTOR_PH]]:
1423
1423
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
1424
1424
; 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:.* ]] ]
1426
1426
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
1427
1427
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1428
1428
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1429
1429
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1430
1430
; 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]]:
1432
1435
; 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]] ]
1435
1448
; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP11]]
1436
1449
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1437
1450
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0
@@ -1491,6 +1504,103 @@ exit:
1491
1504
ret void
1492
1505
}
1493
1506
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 ()
1494
1604
declare void @may_free ()
1495
1605
1496
1606
;.
@@ -1528,4 +1638,6 @@ declare void @may_free()
1528
1638
; CHECK: [[LOOP31]] = distinct !{[[LOOP31]], [[META2]], [[META1]]}
1529
1639
; CHECK: [[LOOP32]] = distinct !{[[LOOP32]], [[META1]], [[META2]]}
1530
1640
; CHECK: [[LOOP33]] = distinct !{[[LOOP33]], [[META2]], [[META1]]}
1641
+ ; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[META1]], [[META2]]}
1642
+ ; CHECK: [[LOOP35]] = distinct !{[[LOOP35]], [[META2]], [[META1]]}
1531
1643
;.
0 commit comments