xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/implied-cond.ll (revision d1d129356909af2f6fefd6f1b9335a39fe172e9a)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 | FileCheck %s
3; Check for when one branch implies the value of a successors conditional and
4; it's not simply the same conditional repeated.
5
6define void @test(i32 %length.i, i32 %i) {
7; CHECK-LABEL: @test(
8; CHECK-NEXT:    [[IPLUS1:%.*]] = add nsw i32 [[I:%.*]], 1
9; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]]
10; CHECK-NEXT:    br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]]
11; CHECK:       in_bounds:
12; CHECK-NEXT:    ret void
13; CHECK:       out_of_bounds:
14; CHECK-NEXT:    call void @foo(i64 0)
15; CHECK-NEXT:    unreachable
16;
17  %iplus1 = add nsw i32 %i, 1
18  %var29 = icmp slt i32 %iplus1, %length.i
19  br i1 %var29, label %next, label %out_of_bounds
20
21next:
22  %var30 = icmp slt i32 %i, %length.i
23  br i1 %var30, label %in_bounds, label %out_of_bounds2
24
25in_bounds:
26  ret void
27
28out_of_bounds:
29  call void @foo(i64 0)
30  unreachable
31
32out_of_bounds2:
33  call void @foo(i64 1)
34  unreachable
35}
36
37; If the add is not nsw, it's not safe to use the fact about i+1 to imply the
38; i condition since it could have overflowed.
39define void @test_neg(i32 %length.i, i32 %i) {
40; CHECK-LABEL: @test_neg(
41; CHECK-NEXT:    [[IPLUS1:%.*]] = add i32 [[I:%.*]], 1
42; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]]
43; CHECK-NEXT:    br i1 [[VAR29]], label [[NEXT:%.*]], label [[OUT_OF_BOUNDS:%.*]]
44; CHECK:       next:
45; CHECK-NEXT:    [[VAR30:%.*]] = icmp slt i32 [[I]], [[LENGTH_I]]
46; CHECK-NEXT:    br i1 [[VAR30]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS2:%.*]]
47; CHECK:       in_bounds:
48; CHECK-NEXT:    ret void
49; CHECK:       out_of_bounds:
50; CHECK-NEXT:    call void @foo(i64 0)
51; CHECK-NEXT:    unreachable
52; CHECK:       out_of_bounds2:
53; CHECK-NEXT:    call void @foo(i64 1)
54; CHECK-NEXT:    unreachable
55;
56  %iplus1 = add i32 %i, 1
57  %var29 = icmp slt i32 %iplus1, %length.i
58  br i1 %var29, label %next, label %out_of_bounds
59
60next:
61  %var30 = icmp slt i32 %i, %length.i
62  br i1 %var30, label %in_bounds, label %out_of_bounds2
63
64in_bounds:
65  ret void
66
67out_of_bounds:
68  call void @foo(i64 0)
69  unreachable
70
71out_of_bounds2:
72  call void @foo(i64 1)
73  unreachable
74}
75
76
77define void @test2(i32 %length.i, i32 %i) {
78; CHECK-LABEL: @test2(
79; CHECK-NEXT:    [[IPLUS100:%.*]] = add nsw i32 [[I:%.*]], 100
80; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 [[IPLUS100]], [[LENGTH_I:%.*]]
81; CHECK-NEXT:    br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]]
82; CHECK:       in_bounds:
83; CHECK-NEXT:    ret void
84; CHECK:       out_of_bounds:
85; CHECK-NEXT:    call void @foo(i64 0)
86; CHECK-NEXT:    unreachable
87;
88  %iplus100 = add nsw i32 %i, 100
89  %var29 = icmp slt i32 %iplus100, %length.i
90  br i1 %var29, label %next, label %out_of_bounds
91
92next:
93  %var30 = icmp slt i32 %i, %length.i
94  br i1 %var30, label %in_bounds, label %out_of_bounds2
95
96in_bounds:
97  ret void
98
99out_of_bounds:
100  call void @foo(i64 0)
101  unreachable
102
103out_of_bounds2:
104  call void @foo(i64 1)
105  unreachable
106}
107
108declare void @foo(i64)
109
110