1; RUN: llvm-as < %s | llvm-dis -expand-constant-exprs | FileCheck %s
2
3@g = extern_weak global i32
4@g2 = extern_weak global i32
5
6define i64 @test_cast() {
7; CHECK-LABEL: define i64 @test_cast() {
8; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
9; CHECK-NEXT: ret i64 %constexpr
10  ret i64 ptrtoint (ptr @g to i64)
11}
12
13define i1 @test_icmp() {
14; CHECK-LABEL: define i1 @test_icmp() {
15; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
16; CHECK-NEXT: %constexpr1 = icmp ne i64 %constexpr, 0
17; CHECK-NEXT: ret i1 %constexpr1
18  ret i1 icmp ne (i64 ptrtoint (ptr @g to i64), i64 0)
19}
20
21define i32 @test_select() {
22; CHECK-LABEL: define i32 @test_select() {
23; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
24; CHECK-NEXT: %constexpr1 = icmp ne i64 %constexpr, 0
25; CHECK-NEXT: %constexpr2 = select i1 %constexpr1, i32 1, i32 2
26; CHECK-NEXT: ret i32 %constexpr2
27  ret i32 select (i1 icmp ne (i64 ptrtoint (ptr @g to i64), i64 0), i32 1, i32 2)
28}
29
30define i8 @test_extractelement() {
31; CHECK-LABEL: define i8 @test_extractelement() {
32; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
33; CHECK-NEXT: %constexpr1 = icmp ne i64 %constexpr, 0
34; CHECK-NEXT: %constexpr2 = select i1 %constexpr1, <2 x i8> zeroinitializer, <2 x i8> <i8 0, i8 1>
35; CHECK-NEXT: %constexpr3 = extractelement <2 x i8> %constexpr2, i32 0
36; CHECK-NEXT: ret i8 %constexpr3
37  ret i8 extractelement (<2 x i8> select (i1 icmp ne (i64 ptrtoint (ptr @g to i64), i64 0), <2 x i8> zeroinitializer, <2 x i8> <i8 0, i8 1>), i32 0)
38}
39
40define <2 x i8> @test_insertelement() {
41; CHECK-LABEL: define <2 x i8> @test_insertelement() {
42; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i32
43; CHECK-NEXT: %constexpr1 = insertelement <2 x i8> poison, i8 42, i32 %constexpr
44; CHECK-NEXT: ret <2 x i8> %constexpr1
45  ret <2 x i8> insertelement (<2 x i8> poison, i8 42, i32 ptrtoint (ptr @g to i32))
46}
47
48define double @test_fneg() {
49; CHECK-LABEL: define double @test_fneg() {
50; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
51; CHECK-NEXT: %constexpr1 = bitcast i64 %constexpr to double
52; CHECK-NEXT: %constexpr2 = fneg double %constexpr1
53  ret double fneg (double bitcast (i64 ptrtoint (ptr @g to i64) to double))
54}
55
56define i64 @test_flags() {
57; CHECK-LABEL: define i64 @test_flags() {
58; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
59; CHECK-NEXT: %constexpr1 = add nuw i64 %constexpr, 1
60; CHECK-NEXT: ret i64 %constexpr1
61  ret i64 add nuw (i64 ptrtoint (ptr @g to i64), i64 1)
62}
63
64define <3 x i64> @test_vector() {
65; CHECK-LABEL: define <3 x i64> @test_vector() {
66; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
67; CHECK-NEXT: %constexpr.ins = insertelement <3 x i64> poison, i64 5, i32 0
68; CHECK-NEXT: %constexpr.ins1 = insertelement <3 x i64> %constexpr.ins, i64 %constexpr, i32 1
69; CHECK-NEXT: %constexpr.ins2 = insertelement <3 x i64> %constexpr.ins1, i64 7, i32 2
70  ret <3 x i64> <i64 5, i64 ptrtoint (ptr @g to i64), i64 7>
71}
72
73define i64 @test_reused_expr() {
74; CHECK-LABEL: define i64 @test_reused_expr() {
75; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
76; CHECK-NEXT: %constexpr1 = add i64 %constexpr, %constexpr
77; CHECK-NEXT: ret i64 %constexpr1
78  ret i64 add (i64 ptrtoint (ptr @g to i64), i64 ptrtoint (ptr @g to i64))
79}
80
81define i64 @test_multiple_expanded_operands() {
82; CHECK-LABEL: define i64 @test_multiple_expanded_operands() {
83; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
84; CHECK-NEXT: %constexpr1 = ptrtoint ptr @g2 to i64
85; CHECK-NEXT: %constexpr2 = add i64 %constexpr, %constexpr1
86; CHECK-NEXT: ret i64 %constexpr2
87  ret i64 add (i64 ptrtoint (ptr @g to i64), i64 ptrtoint (ptr @g2 to i64))
88}
89
90define i64 @test_mid_block(i64 %arg) {
91; CHECK-LABEL: define i64 @test_mid_block(i64 %arg) {
92; CHECK-NEXT: %x = mul i64 %arg, 3
93; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
94; CHECK-NEXT: %add = add i64 %x, %constexpr
95; CHECK-NEXT: ret i64 %add
96  %x = mul i64 %arg, 3
97  %add = add i64 %x, ptrtoint (ptr @g to i64)
98  ret i64 %add
99}
100
101define i64 @test_phi_non_critical_edge_block_before(i1 %c) {
102; CHECK-LABEL: define i64 @test_phi_non_critical_edge_block_before(i1 %c) {
103; CHECK: entry:
104; CHECK-NEXT: br i1 %c, label %if, label %join
105; CHECK: if:
106; CHECK-NEXT: br label %phi.constexpr
107; CHECK: phi.constexpr:
108; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
109; CHECK-NEXT: br label %join
110; CHECK: join:
111; CHECK-NEXT: %phi = phi i64 [ 0, %entry ], [ %constexpr, %phi.constexpr ]
112; CHECK-NEXT: ret i64 %phi
113entry:
114  br i1 %c, label %if, label %join
115
116if:
117  br label %join
118
119join:
120  %phi = phi i64 [ 0, %entry ], [ ptrtoint (ptr @g to i64), %if ]
121  ret i64 %phi
122}
123
124define i64 @test_phi_non_critical_edge_block_after(i1 %c) {
125; CHECK-LABEL: define i64 @test_phi_non_critical_edge_block_after(i1 %c) {
126; CHECK: entry:
127; CHECK-NEXT: br i1 %c, label %if, label %join
128; CHECK: phi.constexpr:
129; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
130; CHECK-NEXT: br label %join
131; CHECK: join:
132; CHECK-NEXT: %phi = phi i64 [ 0, %entry ], [ %constexpr, %phi.constexpr ]
133; CHECK-NEXT: ret i64 %phi
134; CHECK: if:
135; CHECK-NEXT: br label %phi.constexpr
136entry:
137  br i1 %c, label %if, label %join
138
139join:
140  %phi = phi i64 [ 0, %entry ], [ ptrtoint (ptr @g to i64), %if ]
141  ret i64 %phi
142
143if:
144  br label %join
145}
146
147define i64 @test_phi_critical_edge(i1 %c) {
148; CHECK-LABEL: define i64 @test_phi_critical_edge(i1 %c) {
149; CHECK: entry:
150; CHECK-NEXT: br i1 %c, label %if, label %phi.constexpr
151; CHECK: if:
152; CHECK-NEXT: br label %join
153; CHECK: phi.constexpr:
154; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
155; CHECK-NEXT: br label %join
156; CHECK: join:
157; CHECK-NEXT: %phi = phi i64 [ %constexpr, %phi.constexpr ], [ 0, %if ]
158; CHECK-NEXT: ret i64 %phi
159entry:
160  br i1 %c, label %if, label %join
161
162if:
163  br label %join
164
165join:
166  %phi = phi i64 [ ptrtoint (ptr @g to i64), %entry ], [ 0, %if ]
167  ret i64 %phi
168}
169
170define i64 @test_phi_multiple_nodes(i1 %c) {
171; CHECK-LABEL: define i64 @test_phi_multiple_nodes(i1 %c) {
172; CHECK: entry:
173; CHECK-NEXT: br i1 %c, label %if, label %join
174; CHECK: if:
175; CHECK-NEXT: br label %phi.constexpr
176; CHECK: phi.constexpr:
177; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
178; CHECK-NEXT: %constexpr2 = ptrtoint ptr @g2 to i64
179; CHECK-NEXT: br label %join
180; CHECK: join:
181; CHECK-NEXT: %phi = phi i64 [ 0, %entry ], [ %constexpr, %phi.constexpr ]
182; CHECK-NEXT: %phi2 = phi i64 [ 0, %entry ], [ %constexpr2, %phi.constexpr ]
183; CHECK-NEXT: ret i64 %phi
184entry:
185  br i1 %c, label %if, label %join
186
187if:
188  br label %join
189
190join:
191  %phi = phi i64 [ 0, %entry ], [ ptrtoint (ptr @g to i64), %if ]
192  %phi2 = phi i64 [ 0, %entry ], [ ptrtoint (ptr @g2 to i64), %if ]
193  ret i64 %phi
194}
195
196
197define i64 @test_phi_multiple_identical_predecessors(i32 %x) {
198; CHECK-LABEL: define i64 @test_phi_multiple_identical_predecessors(i32 %x) {
199; CHECK: entry:
200; CHECK-NEXT: switch i32 %x, label %default [
201; CHECK-NEXT:   i32 0, label %phi.constexpr
202; CHECK-NEXT:   i32 1, label %phi.constexpr
203; CHECK-NEXT: ]
204; CHECK: default:
205; CHECK-NEXT: br label %join
206; CHECK: phi.constexpr:
207; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
208; CHECK-NEXT: br label %join
209; CHECK: join:
210; CHECK-NEXT: %phi = phi i64 [ %constexpr, %phi.constexpr ], [ %constexpr, %phi.constexpr ], [ 0, %default ]
211; CHECK-NEXT: ret i64 %phi
212entry:
213  switch i32 %x, label %default [
214    i32 0, label %join
215    i32 1, label %join
216  ]
217
218default:
219  br label %join
220
221join:
222  %phi = phi i64 [ ptrtoint (ptr @g to i64), %entry ], [ ptrtoint (ptr @g to i64), %entry ], [ 0, %default ]
223  ret i64 %phi
224}
225