1; RUN: mlir-translate -import-llvm %s | FileCheck %s
2
3%struct.t = type {}
4%struct.s = type { %struct.t, i64 }
5
6; CHECK: llvm.mlir.global external @g1() {alignment = 8 : i64} : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)>
7@g1 = external global %struct.s, align 8
8; CHECK: llvm.mlir.global external @g2() {alignment = 8 : i64} : f64
9@g2 = external global double, align 8
10; CHECK: llvm.mlir.global internal @g3("string")
11@g3 = internal global [6 x i8] c"string"
12
13; CHECK: llvm.mlir.global external @g5() : vector<8xi32>
14@g5 = external global <8 x i32>
15
16; CHECK: llvm.mlir.global private @alig32(42 : i64) {alignment = 32 : i64, dso_local} : i64
17@alig32 = private global i64 42, align 32
18
19; CHECK: llvm.mlir.global private @alig64(42 : i64) {alignment = 64 : i64, dso_local} : i64
20@alig64 = private global i64 42, align 64
21
22@g4 = external global i32, align 8
23; CHECK: llvm.mlir.global internal constant @int_gep() {dso_local} : !llvm.ptr<i32> {
24; CHECK-DAG:   %[[addr:[0-9]+]] = llvm.mlir.addressof @g4 : !llvm.ptr<i32>
25; CHECK-DAG:   %[[c2:[0-9]+]] = llvm.mlir.constant(2 : i32) : i32
26; CHECK-NEXT:  %[[gepinit:[0-9]+]] = llvm.getelementptr %[[addr]][%[[c2]]] : (!llvm.ptr<i32>, i32) -> !llvm.ptr<i32>
27; CHECK-NEXT:  llvm.return %[[gepinit]] : !llvm.ptr<i32>
28; CHECK-NEXT: }
29@int_gep = internal constant i32* getelementptr (i32, i32* @g4, i32 2)
30
31;
32; dso_local attribute
33;
34
35; CHECK: llvm.mlir.global external @dso_local_var() {dso_local} : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)>
36@dso_local_var = external dso_local global %struct.s
37
38;
39; thread_local attribute
40;
41
42; CHECK: llvm.mlir.global external thread_local @thread_local_var() : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)>
43@thread_local_var = external thread_local global %struct.s
44
45;
46; addr_space attribute
47;
48
49; CHECK: llvm.mlir.global external @addr_space_var(0 : i32) {addr_space = 6 : i32} : i32
50@addr_space_var = addrspace(6) global i32 0
51
52;
53; Linkage attribute.
54;
55
56; CHECK: llvm.mlir.global private @private(42 : i32) {dso_local} : i32
57@private = private global i32 42
58; CHECK: llvm.mlir.global internal @internal(42 : i32) {dso_local} : i32
59@internal = internal global i32 42
60; CHECK: llvm.mlir.global available_externally @available_externally(42 : i32) : i32
61@available_externally = available_externally global i32 42
62; CHECK: llvm.mlir.global linkonce @linkonce(42 : i32) : i32
63@linkonce = linkonce global i32 42
64; CHECK: llvm.mlir.global weak @weak(42 : i32) : i32
65@weak = weak global i32 42
66; CHECK: llvm.mlir.global common @common(0 : i32) : i32
67@common = common global i32 zeroinitializer
68; CHECK: llvm.mlir.global appending @appending(dense<[0, 1]> : tensor<2xi32>) : !llvm.array<2 x i32>
69@appending = appending global [2 x i32] [i32 0, i32 1]
70; CHECK: llvm.mlir.global extern_weak @extern_weak() : i32
71@extern_weak = extern_weak global i32
72; CHECK: llvm.mlir.global linkonce_odr @linkonce_odr(42 : i32) : i32
73@linkonce_odr = linkonce_odr global i32 42
74; CHECK: llvm.mlir.global weak_odr @weak_odr(42 : i32) : i32
75@weak_odr = weak_odr global i32 42
76; CHECK: llvm.mlir.global external @external() : i32
77@external = external global i32
78
79;
80; UnnamedAddr attribute.
81;
82
83
84; CHECK: llvm.mlir.global private constant @no_unnamed_addr(42 : i64) {dso_local} : i64
85@no_unnamed_addr = private constant i64 42
86; CHECK: llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i64) {dso_local} : i64
87@local_unnamed_addr = private local_unnamed_addr constant i64 42
88; CHECK: llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) {dso_local} : i64
89@unnamed_addr = private unnamed_addr constant i64 42
90
91;
92; Section attribute
93;
94
95; CHECK: llvm.mlir.global internal constant @sectionvar("teststring") {dso_local, section = ".mysection"}
96@sectionvar = internal constant [10 x i8] c"teststring", section ".mysection"
97
98;
99; Sequential constants.
100;
101
102; CHECK: llvm.mlir.global internal constant @vector_constant(dense<[1, 2]> : vector<2xi32>) {dso_local} : vector<2xi32>
103@vector_constant = internal constant <2 x i32> <i32 1, i32 2>
104; CHECK: llvm.mlir.global internal constant @array_constant(dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf32>) {dso_local} : !llvm.array<2 x f32>
105@array_constant = internal constant [2 x float] [float 1., float 2.]
106; CHECK: llvm.mlir.global internal constant @nested_array_constant(dense<[{{\[}}1, 2], [3, 4]]> : tensor<2x2xi32>) {dso_local} : !llvm.array<2 x array<2 x i32>>
107@nested_array_constant = internal constant [2 x [2 x i32]] [[2 x i32] [i32 1, i32 2], [2 x i32] [i32 3, i32 4]]
108; CHECK: llvm.mlir.global internal constant @nested_array_constant3(dense<[{{\[}}[1, 2], [3, 4]]]> : tensor<1x2x2xi32>) {dso_local} : !llvm.array<1 x array<2 x array<2 x i32>>>
109@nested_array_constant3 = internal constant [1 x [2 x [2 x i32]]] [[2 x [2 x i32]] [[2 x i32] [i32 1, i32 2], [2 x i32] [i32 3, i32 4]]]
110; CHECK: llvm.mlir.global internal constant @nested_array_vector(dense<[{{\[}}[1, 2], [3, 4]]]> : vector<1x2x2xi32>) {dso_local} : !llvm.array<1 x array<2 x vector<2xi32>>>
111@nested_array_vector = internal constant [1 x [2 x <2 x i32>]] [[2 x <2 x i32>] [<2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>]]
112
113;
114; Linkage on functions.
115;
116
117; CHECK: llvm.func internal @func_internal
118define internal void @func_internal() {
119  ret void
120}
121
122; CHECK: llvm.func @fe(i32) -> f32
123declare float @fe(i32)
124
125; FIXME: function attributes.
126; CHECK-LABEL: llvm.func internal @f1(%arg0: i64) -> i32 {
127; CHECK-DAG: %[[c2:[0-9]+]] = llvm.mlir.constant(2 : i32) : i32
128; CHECK-DAG: %[[c42:[0-9]+]] = llvm.mlir.constant(42 : i32) : i32
129; CHECK-DAG: %[[c1:[0-9]+]] = llvm.mlir.constant(true) : i1
130; CHECK-DAG: %[[c43:[0-9]+]] = llvm.mlir.constant(43 : i32) : i32
131define internal dso_local i32 @f1(i64 %a) norecurse {
132entry:
133; CHECK: %{{[0-9]+}} = llvm.inttoptr %arg0 : i64 to !llvm.ptr<i64>
134  %aa = inttoptr i64 %a to i64*
135; %[[addrof:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
136; %[[addrof2:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
137; %{{[0-9]+}} = llvm.inttoptr %arg0 : i64 to !llvm.ptr<i64>
138; %{{[0-9]+}} = llvm.ptrtoint %[[addrof2]] : !llvm.ptr<f64> to i64
139; %{{[0-9]+}} = llvm.getelementptr %[[addrof]][%3] : (!llvm.ptr<f64>, i32) -> !llvm.ptr<f64>
140  %bb = ptrtoint double* @g2 to i64
141  %cc = getelementptr double, double* @g2, i32 2
142; CHECK: %[[b:[0-9]+]] = llvm.trunc %arg0 : i64 to i32
143  %b = trunc i64 %a to i32
144; CHECK: %[[c:[0-9]+]] = llvm.call @fe(%[[b]]) : (i32) -> f32
145  %c = call float @fe(i32 %b)
146; CHECK: %[[d:[0-9]+]] = llvm.fptosi %[[c]] : f32 to i32
147  %d = fptosi float %c to i32
148; FIXME: icmp should return i1.
149; CHECK: %[[e:[0-9]+]] = llvm.icmp "ne" %[[d]], %[[c2]] : i32
150  %e = icmp ne i32 %d, 2
151; CHECK: llvm.cond_br %[[e]], ^bb1, ^bb2
152  br i1 %e, label %if.then, label %if.end
153
154; CHECK: ^bb1:
155if.then:
156; CHECK: llvm.return %[[c42]] : i32
157  ret i32 42
158
159; CHECK: ^bb2:
160if.end:
161; CHECK: %[[orcond:[0-9]+]] = llvm.or %[[e]], %[[c1]] : i1
162  %or.cond = or i1 %e, 1
163; CHECK: llvm.return %[[c43]]
164  ret i32 43
165}
166
167; Test that instructions that dominate can be out of sequential order.
168; CHECK-LABEL: llvm.func @f2(%arg0: i64) -> i64 {
169; CHECK-DAG: %[[c3:[0-9]+]] = llvm.mlir.constant(3 : i64) : i64
170define i64 @f2(i64 %a) noduplicate {
171entry:
172; CHECK: llvm.br ^bb2
173  br label %next
174
175; CHECK: ^bb1:
176end:
177; CHECK: llvm.return %1
178  ret i64 %b
179
180; CHECK: ^bb2:
181next:
182; CHECK: %1 = llvm.add %arg0, %[[c3]] : i64
183  %b = add i64 %a, 3
184; CHECK: llvm.br ^bb1
185  br label %end
186}
187
188; Test arguments/phis.
189; CHECK-LABEL: llvm.func @f2_phis(%arg0: i64) -> i64 {
190; CHECK-DAG: %[[c3:[0-9]+]] = llvm.mlir.constant(3 : i64) : i64
191define i64 @f2_phis(i64 %a) noduplicate {
192entry:
193; CHECK: llvm.br ^bb2
194  br label %next
195
196; CHECK: ^bb1(%1: i64):
197end:
198  %c = phi i64 [ %b, %next ]
199; CHECK: llvm.return %1
200  ret i64 %c
201
202; CHECK: ^bb2:
203next:
204; CHECK: %2 = llvm.add %arg0, %[[c3]] : i64
205  %b = add i64 %a, 3
206; CHECK: llvm.br ^bb1
207  br label %end
208}
209
210; CHECK-LABEL: llvm.func @f3() -> !llvm.ptr<i32>
211define i32* @f3() {
212; CHECK: %[[c:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
213; CHECK: %[[b:[0-9]+]] = llvm.bitcast %[[c]] : !llvm.ptr<f64> to !llvm.ptr<i32>
214; CHECK: llvm.return %[[b]] : !llvm.ptr<i32>
215  ret i32* bitcast (double* @g2 to i32*)
216}
217
218; CHECK-LABEL: llvm.func @f4() -> !llvm.ptr<i32>
219define i32* @f4() {
220; CHECK: %[[b:[0-9]+]] = llvm.mlir.null : !llvm.ptr<i32>
221; CHECK: llvm.return %[[b]] : !llvm.ptr<i32>
222  ret i32* bitcast (double* null to i32*)
223}
224
225; CHECK-LABEL: llvm.func @f5
226define void @f5(i32 %d) {
227; FIXME: icmp should return i1.
228; CHECK: = llvm.icmp "eq"
229  %1 = icmp eq i32 %d, 2
230; CHECK: = llvm.icmp "slt"
231  %2 = icmp slt i32 %d, 2
232; CHECK: = llvm.icmp "sle"
233  %3 = icmp sle i32 %d, 2
234; CHECK: = llvm.icmp "sgt"
235  %4 = icmp sgt i32 %d, 2
236; CHECK: = llvm.icmp "sge"
237  %5 = icmp sge i32 %d, 2
238; CHECK: = llvm.icmp "ult"
239  %6 = icmp ult i32 %d, 2
240; CHECK: = llvm.icmp "ule"
241  %7 = icmp ule i32 %d, 2
242; CHECK: = llvm.icmp "ugt"
243  %8 = icmp ugt i32 %d, 2
244  ret void
245}
246
247; CHECK-LABEL: llvm.func @f6(%arg0: !llvm.ptr<func<void (i16)>>)
248define void @f6(void (i16) *%fn) {
249; CHECK: %[[c:[0-9]+]] = llvm.mlir.constant(0 : i16) : i16
250; CHECK: llvm.call %arg0(%[[c]])
251  call void %fn(i16 0)
252  ret void
253}
254
255; CHECK-LABEL: llvm.func @FPArithmetic(%arg0: f32, %arg1: f32, %arg2: f64, %arg3: f64)
256define void @FPArithmetic(float %a, float %b, double %c, double %d) {
257  ; CHECK: %[[a1:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f64) : f64
258  ; CHECK: %[[a2:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f32) : f32
259  ; CHECK: %[[a3:[0-9]+]] = llvm.fadd %[[a2]], %arg0 : f32
260  %1 = fadd float 0x403E4CCCC0000000, %a
261  ; CHECK: %[[a4:[0-9]+]] = llvm.fadd %arg0, %arg1 : f32
262  %2 = fadd float %a, %b
263  ; CHECK: %[[a5:[0-9]+]] = llvm.fadd %[[a1]], %arg2 : f64
264  %3 = fadd double 3.030000e+01, %c
265  ; CHECK: %[[a6:[0-9]+]] = llvm.fsub %arg0, %arg1 : f32
266  %4 = fsub float %a, %b
267  ; CHECK: %[[a7:[0-9]+]] = llvm.fsub %arg2, %arg3 : f64
268  %5 = fsub double %c, %d
269  ; CHECK: %[[a8:[0-9]+]] = llvm.fmul %arg0, %arg1 : f32
270  %6 = fmul float %a, %b
271  ; CHECK: %[[a9:[0-9]+]] = llvm.fmul %arg2, %arg3 : f64
272  %7 = fmul double %c, %d
273  ; CHECK: %[[a10:[0-9]+]] = llvm.fdiv %arg0, %arg1 : f32
274  %8 = fdiv float %a, %b
275  ; CHECK: %[[a12:[0-9]+]] = llvm.fdiv %arg2, %arg3 : f64
276  %9 = fdiv double %c, %d
277  ; CHECK: %[[a11:[0-9]+]] = llvm.frem %arg0, %arg1 : f32
278  %10 = frem float %a, %b
279  ; CHECK: %[[a13:[0-9]+]] = llvm.frem %arg2, %arg3 : f64
280  %11 = frem double %c, %d
281  ret void
282}
283
284;
285; Functions as constants.
286;
287
288; Calling the function that has not been defined yet.
289; CHECK-LABEL: @precaller
290define i32 @precaller() {
291  %1 = alloca i32 ()*
292  ; CHECK: %[[func:.*]] = llvm.mlir.addressof @callee : !llvm.ptr<func<i32 ()>>
293  ; CHECK: llvm.store %[[func]], %[[loc:.*]]
294  store i32 ()* @callee, i32 ()** %1
295  ; CHECK: %[[indir:.*]] = llvm.load %[[loc]]
296  %2 = load i32 ()*, i32 ()** %1
297  ; CHECK: llvm.call %[[indir]]()
298  %3 = call i32 %2()
299  ret i32 %3
300}
301
302define i32 @callee() {
303  ret i32 42
304}
305
306; Calling the function that has been defined.
307; CHECK-LABEL: @postcaller
308define i32 @postcaller() {
309  %1 = alloca i32 ()*
310  ; CHECK: %[[func:.*]] = llvm.mlir.addressof @callee : !llvm.ptr<func<i32 ()>>
311  ; CHECK: llvm.store %[[func]], %[[loc:.*]]
312  store i32 ()* @callee, i32 ()** %1
313  ; CHECK: %[[indir:.*]] = llvm.load %[[loc]]
314  %2 = load i32 ()*, i32 ()** %1
315  ; CHECK: llvm.call %[[indir]]()
316  %3 = call i32 %2()
317  ret i32 %3
318}
319
320@_ZTIi = external dso_local constant i8*
321@_ZTIii= external dso_local constant i8**
322declare void @foo(i8*)
323declare i8* @bar(i8*)
324declare i32 @__gxx_personality_v0(...)
325
326; CHECK-LABEL: @invokeLandingpad
327define i32 @invokeLandingpad() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
328  ; CHECK: %[[a1:[0-9]+]] = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<ptr<ptr<i8>>> to !llvm.ptr<i8>
329  ; CHECK: %[[a3:[0-9]+]] = llvm.alloca %{{[0-9]+}} x i8 {alignment = 1 : i64} : (i32) -> !llvm.ptr<i8>
330  %1 = alloca i8
331  ; CHECK: llvm.invoke @foo(%[[a3]]) to ^bb2 unwind ^bb1 : (!llvm.ptr<i8>) -> ()
332  invoke void @foo(i8* %1) to label %4 unwind label %2
333
334; CHECK: ^bb1:
335  ; CHECK: %{{[0-9]+}} = llvm.landingpad (catch %{{[0-9]+}} : !llvm.ptr<ptr<i8>>) (catch %[[a1]] : !llvm.ptr<i8>) (filter %{{[0-9]+}} : !llvm.array<1 x i8>) : !llvm.struct<(ptr<i8>, i32)>
336  %3 = landingpad { i8*, i32 } catch i8** @_ZTIi catch i8* bitcast (i8*** @_ZTIii to i8*)
337  ; FIXME: Change filter to a constant array once they are handled.
338  ; Currently, even though it parses this, LLVM module is broken
339          filter [1 x i8] [i8 1]
340  resume { i8*, i32 } %3
341
342; CHECK: ^bb2:
343  ; CHECK: llvm.return %{{[0-9]+}} : i32
344  ret i32 1
345
346; CHECK: ^bb3:
347  ; CHECK: %{{[0-9]+}} = llvm.invoke @bar(%[[a3]]) to ^bb2 unwind ^bb1 : (!llvm.ptr<i8>) -> !llvm.ptr<i8>
348  %6 = invoke i8* @bar(i8* %1) to label %4 unwind label %2
349
350; CHECK: ^bb4:
351  ; CHECK: llvm.return %{{[0-9]+}} : i32
352  ret i32 0
353}
354
355; CHECK-LABEL: @hasGCFunction
356; CHECK-SAME: garbageCollector = "statepoint-example"
357define void @hasGCFunction() gc "statepoint-example" {
358    ret void
359}
360
361;CHECK-LABEL: @useFreezeOp
362define i32 @useFreezeOp(i32 %x) {
363  ;CHECK: %{{[0-9]+}} = llvm.freeze %{{[0-9a-z]+}} : i32
364  %1 = freeze i32 %x
365  %2 = add i8 10, 10
366  ;CHECK: %{{[0-9]+}} = llvm.freeze %{{[0-9]+}} : i8
367  %3 = freeze i8 %2
368  %poison = add nsw i1 0, undef
369  ret i32 0
370}
371
372;CHECK-LABEL: @useFenceInst
373define i32 @useFenceInst() {
374  ;CHECK: llvm.fence syncscope("agent") seq_cst
375  fence syncscope("agent") seq_cst
376  ;CHECK: llvm.fence release
377  fence release
378  ;CHECK: llvm.fence seq_cst
379  fence syncscope("") seq_cst
380  ret i32 0
381}
382