xref: /llvm-project/llvm/test/Transforms/SCCP/constant-range-struct.ll (revision 8ebb3eac02a926ffa4298c12834c57aefb2e8579)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -passes=ipsccp -S | FileCheck %s
3
4declare i1 @cond()
5declare void @use(i1)
6
7define internal {i64, i64} @struct1() {
8; CHECK-LABEL: @struct1(
9; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
10; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
11; CHECK:       true:
12; CHECK-NEXT:    br label [[EXIT:%.*]]
13; CHECK:       false:
14; CHECK-NEXT:    br label [[EXIT]]
15; CHECK:       exit:
16; CHECK-NEXT:    [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ]
17; CHECK-NEXT:    ret { i64, i64 } [[R]]
18;
19  %c = call i1 @cond()
20  br i1 %c, label %true, label %false
21
22true:
23  %s.1 = insertvalue {i64, i64} undef, i64 20, 0
24  %s.2 = insertvalue {i64, i64} %s.1, i64 200, 1
25  br label %exit
26
27false:
28  %s.3 = insertvalue {i64, i64} undef, i64 30, 0
29  %s.4 = insertvalue {i64, i64} %s.3, i64 300, 1
30  br label %exit
31
32exit:
33  %r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ]
34  ret {i64, i64} %r
35}
36
37define void @struct1_caller() {
38; CHECK-LABEL: @struct1_caller(
39; CHECK-NEXT:    [[S:%.*]] = call { i64, i64 } @struct1()
40; CHECK-NEXT:    [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
41; CHECK-NEXT:    [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
42; CHECK-NEXT:    [[T_1:%.*]] = icmp ne i64 [[V1]], 10
43; CHECK-NEXT:    call void @use(i1 [[T_1]])
44; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i64 [[V1]], 100
45; CHECK-NEXT:    call void @use(i1 [[T_2]])
46; CHECK-NEXT:    [[T_3:%.*]] = icmp ne i64 [[V2]], 0
47; CHECK-NEXT:    call void @use(i1 [[T_3]])
48; CHECK-NEXT:    [[T_4:%.*]] = icmp ult i64 [[V2]], 301
49; CHECK-NEXT:    call void @use(i1 [[T_4]])
50; CHECK-NEXT:    ret void
51;
52  %s = call {i64, i64} @struct1()
53  %v1 = extractvalue {i64, i64} %s, 0
54  %v2 = extractvalue {i64, i64} %s, 1
55
56  %t.1 = icmp ne i64 %v1, 10
57  call void @use(i1 %t.1)
58  %t.2 = icmp ult i64 %v1, 100
59  call void @use(i1 %t.2)
60  %t.3 = icmp ne i64 %v2, 0
61  call void @use(i1 %t.3)
62  %t.4 = icmp ult i64 %v2, 301
63  call void @use(i1 %t.4)
64
65  ret void
66}
67
68define internal {i64, i64} @struct2() {
69; CHECK-LABEL: @struct2(
70; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
71; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
72; CHECK:       true:
73; CHECK-NEXT:    br label [[EXIT:%.*]]
74; CHECK:       false:
75; CHECK-NEXT:    br label [[EXIT]]
76; CHECK:       exit:
77; CHECK-NEXT:    [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ]
78; CHECK-NEXT:    [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ]
79; CHECK-NEXT:    [[S_1:%.*]] = insertvalue { i64, i64 } undef, i64 [[V1]], 0
80; CHECK-NEXT:    [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1
81; CHECK-NEXT:    ret { i64, i64 } [[S_2]]
82;
83  %c = call i1 @cond()
84  br i1 %c, label %true, label %false
85
86true:
87  br label %exit
88
89false:
90  br label %exit
91
92exit:
93  %v1 = phi i64 [ 20, %true ], [ 30, %false ]
94  %v2 = phi i64 [ 200, %true ], [ 300, %false ]
95  %s.1 = insertvalue {i64, i64} undef, i64 %v1, 0
96  %s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1
97  ret {i64, i64} %s.2
98}
99
100define void @struct2_caller() {
101; CHECK-LABEL: @struct2_caller(
102; CHECK-NEXT:    [[S:%.*]] = call { i64, i64 } @struct2()
103; CHECK-NEXT:    [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
104; CHECK-NEXT:    [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
105; CHECK-NEXT:    call void @use(i1 true)
106; CHECK-NEXT:    call void @use(i1 true)
107; CHECK-NEXT:    call void @use(i1 true)
108; CHECK-NEXT:    call void @use(i1 true)
109; CHECK-NEXT:    call void @use(i1 false)
110; CHECK-NEXT:    call void @use(i1 false)
111; CHECK-NEXT:    call void @use(i1 false)
112; CHECK-NEXT:    call void @use(i1 false)
113; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i64 [[V1]], 25
114; CHECK-NEXT:    call void @use(i1 [[C_1]])
115; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i64 [[V1]], 25
116; CHECK-NEXT:    call void @use(i1 [[C_2]])
117; CHECK-NEXT:    [[C_3:%.*]] = icmp eq i64 [[V2]], 250
118; CHECK-NEXT:    call void @use(i1 [[C_3]])
119; CHECK-NEXT:    [[C_4:%.*]] = icmp ugt i64 [[V2]], 250
120; CHECK-NEXT:    call void @use(i1 [[C_4]])
121; CHECK-NEXT:    ret void
122;
123  %s = call {i64, i64} @struct2()
124  %v1 = extractvalue {i64, i64} %s, 0
125  %v2 = extractvalue {i64, i64} %s, 1
126
127  %t.1 = icmp ne i64 %v1, 10
128  call void @use(i1 %t.1)
129  %t.2 = icmp ult i64 %v1, 100
130  call void @use(i1 %t.2)
131  %t.3 = icmp ne i64 %v2, 0
132  call void @use(i1 %t.3)
133  %t.4 = icmp ult i64 %v2, 301
134  call void @use(i1 %t.4)
135
136  %f.1 = icmp eq i64 %v1, 10
137  call void @use(i1 %f.1)
138  %f.2 = icmp ult i64 %v1, 19
139  call void @use(i1 %f.2)
140  %f.3 = icmp eq i64 %v2, 50
141  call void @use(i1 %f.3)
142  %f.4 = icmp ugt i64 %v2, 301
143  call void @use(i1 %f.4)
144
145  %c.1 = icmp eq i64 %v1, 25
146  call void @use(i1 %c.1)
147  %c.2 = icmp ult i64 %v1, 25
148  call void @use(i1 %c.2)
149  %c.3 = icmp eq i64 %v2, 250
150  call void @use(i1 %c.3)
151  %c.4 = icmp ugt i64 %v2, 250
152  call void @use(i1 %c.4)
153
154  ret void
155}
156