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; CHECK: llvm.func internal spir_funccc @spir_func_internal()
126define internal spir_func void @spir_func_internal() {
127  ret void
128}
129
130; FIXME: function attributes.
131; CHECK-LABEL: llvm.func internal @f1(%arg0: i64) -> i32 attributes {dso_local} {
132; CHECK-DAG: %[[c2:[0-9]+]] = llvm.mlir.constant(2 : i32) : i32
133; CHECK-DAG: %[[c42:[0-9]+]] = llvm.mlir.constant(42 : i32) : i32
134; CHECK-DAG: %[[c1:[0-9]+]] = llvm.mlir.constant(true) : i1
135; CHECK-DAG: %[[c43:[0-9]+]] = llvm.mlir.constant(43 : i32) : i32
136define internal dso_local i32 @f1(i64 %a) norecurse {
137entry:
138; CHECK: %{{[0-9]+}} = llvm.inttoptr %arg0 : i64 to !llvm.ptr<i64>
139  %aa = inttoptr i64 %a to i64*
140; %[[addrof:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
141; %[[addrof2:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
142; %{{[0-9]+}} = llvm.inttoptr %arg0 : i64 to !llvm.ptr<i64>
143; %{{[0-9]+}} = llvm.ptrtoint %[[addrof2]] : !llvm.ptr<f64> to i64
144; %{{[0-9]+}} = llvm.getelementptr %[[addrof]][%3] : (!llvm.ptr<f64>, i32) -> !llvm.ptr<f64>
145  %bb = ptrtoint double* @g2 to i64
146  %cc = getelementptr double, double* @g2, i32 2
147; CHECK: %[[b:[0-9]+]] = llvm.trunc %arg0 : i64 to i32
148  %b = trunc i64 %a to i32
149; CHECK: %[[c:[0-9]+]] = llvm.call @fe(%[[b]]) : (i32) -> f32
150  %c = call float @fe(i32 %b)
151; CHECK: %[[d:[0-9]+]] = llvm.fptosi %[[c]] : f32 to i32
152  %d = fptosi float %c to i32
153; FIXME: icmp should return i1.
154; CHECK: %[[e:[0-9]+]] = llvm.icmp "ne" %[[d]], %[[c2]] : i32
155  %e = icmp ne i32 %d, 2
156; CHECK: llvm.cond_br %[[e]], ^bb1, ^bb2
157  br i1 %e, label %if.then, label %if.end
158
159; CHECK: ^bb1:
160if.then:
161; CHECK: llvm.return %[[c42]] : i32
162  ret i32 42
163
164; CHECK: ^bb2:
165if.end:
166; CHECK: %[[orcond:[0-9]+]] = llvm.or %[[e]], %[[c1]] : i1
167  %or.cond = or i1 %e, 1
168; CHECK: llvm.return %[[c43]]
169  ret i32 43
170}
171
172; Test that instructions that dominate can be out of sequential order.
173; CHECK-LABEL: llvm.func @f2(%arg0: i64) -> i64 {
174; CHECK-DAG: %[[c3:[0-9]+]] = llvm.mlir.constant(3 : i64) : i64
175define i64 @f2(i64 %a) noduplicate {
176entry:
177; CHECK: llvm.br ^bb2
178  br label %next
179
180; CHECK: ^bb1:
181end:
182; CHECK: llvm.return %1
183  ret i64 %b
184
185; CHECK: ^bb2:
186next:
187; CHECK: %1 = llvm.add %arg0, %[[c3]] : i64
188  %b = add i64 %a, 3
189; CHECK: llvm.br ^bb1
190  br label %end
191}
192
193; Test arguments/phis.
194; CHECK-LABEL: llvm.func @f2_phis(%arg0: i64) -> i64 {
195; CHECK-DAG: %[[c3:[0-9]+]] = llvm.mlir.constant(3 : i64) : i64
196define i64 @f2_phis(i64 %a) noduplicate {
197entry:
198; CHECK: llvm.br ^bb2
199  br label %next
200
201; CHECK: ^bb1(%1: i64):
202end:
203  %c = phi i64 [ %b, %next ]
204; CHECK: llvm.return %1
205  ret i64 %c
206
207; CHECK: ^bb2:
208next:
209; CHECK: %2 = llvm.add %arg0, %[[c3]] : i64
210  %b = add i64 %a, 3
211; CHECK: llvm.br ^bb1
212  br label %end
213}
214
215; CHECK-LABEL: llvm.func @f3() -> !llvm.ptr<i32>
216define i32* @f3() {
217; CHECK: %[[c:[0-9]+]] = llvm.mlir.addressof @g2 : !llvm.ptr<f64>
218; CHECK: %[[b:[0-9]+]] = llvm.bitcast %[[c]] : !llvm.ptr<f64> to !llvm.ptr<i32>
219; CHECK: llvm.return %[[b]] : !llvm.ptr<i32>
220  ret i32* bitcast (double* @g2 to i32*)
221}
222
223; CHECK-LABEL: llvm.func @f4() -> !llvm.ptr<i32>
224define i32* @f4() {
225; CHECK: %[[b:[0-9]+]] = llvm.mlir.null : !llvm.ptr<i32>
226; CHECK: llvm.return %[[b]] : !llvm.ptr<i32>
227  ret i32* bitcast (double* null to i32*)
228}
229
230; CHECK-LABEL: llvm.func @f5
231define void @f5(i32 %d) {
232; FIXME: icmp should return i1.
233; CHECK: = llvm.icmp "eq"
234  %1 = icmp eq i32 %d, 2
235; CHECK: = llvm.icmp "slt"
236  %2 = icmp slt i32 %d, 2
237; CHECK: = llvm.icmp "sle"
238  %3 = icmp sle i32 %d, 2
239; CHECK: = llvm.icmp "sgt"
240  %4 = icmp sgt i32 %d, 2
241; CHECK: = llvm.icmp "sge"
242  %5 = icmp sge i32 %d, 2
243; CHECK: = llvm.icmp "ult"
244  %6 = icmp ult i32 %d, 2
245; CHECK: = llvm.icmp "ule"
246  %7 = icmp ule i32 %d, 2
247; CHECK: = llvm.icmp "ugt"
248  %8 = icmp ugt i32 %d, 2
249  ret void
250}
251
252; CHECK-LABEL: llvm.func @f6(%arg0: !llvm.ptr<func<void (i16)>>)
253define void @f6(void (i16) *%fn) {
254; CHECK: %[[c:[0-9]+]] = llvm.mlir.constant(0 : i16) : i16
255; CHECK: llvm.call %arg0(%[[c]])
256  call void %fn(i16 0)
257  ret void
258}
259
260; CHECK-LABEL: llvm.func @FPArithmetic(%arg0: f32, %arg1: f32, %arg2: f64, %arg3: f64)
261define void @FPArithmetic(float %a, float %b, double %c, double %d) {
262  ; CHECK: %[[a1:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f64) : f64
263  ; CHECK: %[[a2:[0-9]+]] = llvm.mlir.constant(3.030000e+01 : f32) : f32
264  ; CHECK: %[[a3:[0-9]+]] = llvm.fadd %[[a2]], %arg0 : f32
265  %1 = fadd float 0x403E4CCCC0000000, %a
266  ; CHECK: %[[a4:[0-9]+]] = llvm.fadd %arg0, %arg1 : f32
267  %2 = fadd float %a, %b
268  ; CHECK: %[[a5:[0-9]+]] = llvm.fadd %[[a1]], %arg2 : f64
269  %3 = fadd double 3.030000e+01, %c
270  ; CHECK: %[[a6:[0-9]+]] = llvm.fsub %arg0, %arg1 : f32
271  %4 = fsub float %a, %b
272  ; CHECK: %[[a7:[0-9]+]] = llvm.fsub %arg2, %arg3 : f64
273  %5 = fsub double %c, %d
274  ; CHECK: %[[a8:[0-9]+]] = llvm.fmul %arg0, %arg1 : f32
275  %6 = fmul float %a, %b
276  ; CHECK: %[[a9:[0-9]+]] = llvm.fmul %arg2, %arg3 : f64
277  %7 = fmul double %c, %d
278  ; CHECK: %[[a10:[0-9]+]] = llvm.fdiv %arg0, %arg1 : f32
279  %8 = fdiv float %a, %b
280  ; CHECK: %[[a12:[0-9]+]] = llvm.fdiv %arg2, %arg3 : f64
281  %9 = fdiv double %c, %d
282  ; CHECK: %[[a11:[0-9]+]] = llvm.frem %arg0, %arg1 : f32
283  %10 = frem float %a, %b
284  ; CHECK: %[[a13:[0-9]+]] = llvm.frem %arg2, %arg3 : f64
285  %11 = frem double %c, %d
286  ; CHECK: %{{.+}} = llvm.fneg %{{.+}} : f32
287  %12 = fneg float %a
288  ; CHECK: %{{.+}} = llvm.fneg %{{.+}} : f64
289  %13 = fneg double %c
290  ret void
291}
292
293; CHECK-LABEL: llvm.func @FPComparison(%arg0: f32, %arg1: f32)
294define void @FPComparison(float %a, float %b) {
295  ; CHECK: llvm.fcmp "_false" %arg0, %arg1
296  %1 = fcmp false float %a, %b
297  ; CHECK: llvm.fcmp "oeq" %arg0, %arg1
298  %2 = fcmp oeq float %a, %b
299  ; CHECK: llvm.fcmp "ogt" %arg0, %arg1
300  %3 = fcmp ogt float %a, %b
301  ; CHECK: llvm.fcmp "oge" %arg0, %arg1
302  %4 = fcmp oge float %a, %b
303  ; CHECK: llvm.fcmp "olt" %arg0, %arg1
304  %5 = fcmp olt float %a, %b
305  ; CHECK: llvm.fcmp "ole" %arg0, %arg1
306  %6 = fcmp ole float %a, %b
307  ; CHECK: llvm.fcmp "one" %arg0, %arg1
308  %7 = fcmp one float %a, %b
309  ; CHECK: llvm.fcmp "ord" %arg0, %arg1
310  %8 = fcmp ord float %a, %b
311  ; CHECK: llvm.fcmp "ueq" %arg0, %arg1
312  %9 = fcmp ueq float %a, %b
313  ; CHECK: llvm.fcmp "ugt" %arg0, %arg1
314  %10 = fcmp ugt float %a, %b
315  ; CHECK: llvm.fcmp "uge" %arg0, %arg1
316  %11 = fcmp uge float %a, %b
317  ; CHECK: llvm.fcmp "ult" %arg0, %arg1
318  %12 = fcmp ult float %a, %b
319  ; CHECK: llvm.fcmp "ule" %arg0, %arg1
320  %13 = fcmp ule float %a, %b
321  ; CHECK: llvm.fcmp "une" %arg0, %arg1
322  %14 = fcmp une float %a, %b
323  ; CHECK: llvm.fcmp "uno" %arg0, %arg1
324  %15 = fcmp uno float %a, %b
325  ; CHECK: llvm.fcmp "_true" %arg0, %arg1
326  %16 = fcmp true float %a, %b
327  ret void
328}
329
330; Testing rest of the floating point constant kinds.
331; CHECK-LABEL: llvm.func @FPConstant(%arg0: f16, %arg1: bf16, %arg2: f128, %arg3: f80)
332define void @FPConstant(half %a, bfloat %b, fp128 %c, x86_fp80 %d) {
333  ; CHECK-DAG: %[[C0:.+]] = llvm.mlir.constant(7.000000e+00 : f80) : f80
334  ; CHECK-DAG: %[[C1:.+]] = llvm.mlir.constant(0.000000e+00 : f128) : f128
335  ; CHECK-DAG: %[[C2:.+]] = llvm.mlir.constant(1.000000e+00 : bf16) : bf16
336  ; CHECK-DAG: %[[C3:.+]] = llvm.mlir.constant(1.000000e+00 : f16) : f16
337
338  ; CHECK: llvm.fadd %[[C3]], %arg0  : f16
339  %1 = fadd half 1.0, %a
340  ; CHECK: llvm.fadd %[[C2]], %arg1  : bf16
341  %2 = fadd bfloat 1.0, %b
342  ; CHECK: llvm.fadd %[[C1]], %arg2  : f128
343  %3 = fadd fp128 0xL00000000000000000000000000000000, %c
344  ; CHECK: llvm.fadd %[[C0]], %arg3  : f80
345  %4 = fadd x86_fp80 0xK4001E000000000000000, %d
346  ret void
347}
348
349;
350; Functions as constants.
351;
352
353; Calling the function that has not been defined yet.
354; CHECK-LABEL: @precaller
355define i32 @precaller() {
356  %1 = alloca i32 ()*
357  ; CHECK: %[[func:.*]] = llvm.mlir.addressof @callee : !llvm.ptr<func<i32 ()>>
358  ; CHECK: llvm.store %[[func]], %[[loc:.*]]
359  store i32 ()* @callee, i32 ()** %1
360  ; CHECK: %[[indir:.*]] = llvm.load %[[loc]]
361  %2 = load i32 ()*, i32 ()** %1
362  ; CHECK: llvm.call %[[indir]]()
363  %3 = call i32 %2()
364  ret i32 %3
365}
366
367define i32 @callee() {
368  ret i32 42
369}
370
371; Calling the function that has been defined.
372; CHECK-LABEL: @postcaller
373define i32 @postcaller() {
374  %1 = alloca i32 ()*
375  ; CHECK: %[[func:.*]] = llvm.mlir.addressof @callee : !llvm.ptr<func<i32 ()>>
376  ; CHECK: llvm.store %[[func]], %[[loc:.*]]
377  store i32 ()* @callee, i32 ()** %1
378  ; CHECK: %[[indir:.*]] = llvm.load %[[loc]]
379  %2 = load i32 ()*, i32 ()** %1
380  ; CHECK: llvm.call %[[indir]]()
381  %3 = call i32 %2()
382  ret i32 %3
383}
384
385@_ZTIi = external dso_local constant i8*
386@_ZTIii= external dso_local constant i8**
387declare void @foo(i8*)
388declare i8* @bar(i8*)
389declare i32 @__gxx_personality_v0(...)
390
391; CHECK-LABEL: @invokeLandingpad
392define i32 @invokeLandingpad() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
393  ; CHECK: %[[a1:[0-9]+]] = llvm.bitcast %{{[0-9]+}} : !llvm.ptr<ptr<ptr<i8>>> to !llvm.ptr<i8>
394  ; CHECK: %[[a3:[0-9]+]] = llvm.alloca %{{[0-9]+}} x i8 {alignment = 1 : i64} : (i32) -> !llvm.ptr<i8>
395  %1 = alloca i8
396  ; CHECK: llvm.invoke @foo(%[[a3]]) to ^bb2 unwind ^bb1 : (!llvm.ptr<i8>) -> ()
397  invoke void @foo(i8* %1) to label %4 unwind label %2
398
399; CHECK: ^bb1:
400  ; 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)>
401  %3 = landingpad { i8*, i32 } catch i8** @_ZTIi catch i8* bitcast (i8*** @_ZTIii to i8*)
402  ; FIXME: Change filter to a constant array once they are handled.
403  ; Currently, even though it parses this, LLVM module is broken
404          filter [1 x i8] [i8 1]
405  resume { i8*, i32 } %3
406
407; CHECK: ^bb2:
408  ; CHECK: llvm.return %{{[0-9]+}} : i32
409  ret i32 1
410
411; CHECK: ^bb3:
412  ; CHECK: %{{[0-9]+}} = llvm.invoke @bar(%[[a3]]) to ^bb2 unwind ^bb1 : (!llvm.ptr<i8>) -> !llvm.ptr<i8>
413  %6 = invoke i8* @bar(i8* %1) to label %4 unwind label %2
414
415; CHECK: ^bb4:
416  ; CHECK: llvm.return %{{[0-9]+}} : i32
417  ret i32 0
418}
419
420; CHECK-LABEL: @hasGCFunction
421; CHECK-SAME: garbageCollector = "statepoint-example"
422define void @hasGCFunction() gc "statepoint-example" {
423    ret void
424}
425
426;CHECK-LABEL: @useFreezeOp
427define i32 @useFreezeOp(i32 %x) {
428  ;CHECK: %{{[0-9]+}} = llvm.freeze %{{[0-9a-z]+}} : i32
429  %1 = freeze i32 %x
430  %2 = add i8 10, 10
431  ;CHECK: %{{[0-9]+}} = llvm.freeze %{{[0-9]+}} : i8
432  %3 = freeze i8 %2
433  %poison = add nsw i1 0, undef
434  ret i32 0
435}
436
437;CHECK-LABEL: @useFenceInst
438define i32 @useFenceInst() {
439  ;CHECK: llvm.fence syncscope("agent") seq_cst
440  fence syncscope("agent") seq_cst
441  ;CHECK: llvm.fence release
442  fence release
443  ;CHECK: llvm.fence seq_cst
444  fence syncscope("") seq_cst
445  ret i32 0
446}
447
448; Switch instruction
449declare void @g(i32)
450
451; CHECK-LABEL: llvm.func @simple_switch(%arg0: i32) {
452define void @simple_switch(i32 %val) {
453; CHECK: %[[C0:.+]] = llvm.mlir.constant(11 : i32) : i32
454; CHECK: %[[C1:.+]] = llvm.mlir.constant(87 : i32) : i32
455; CHECK: %[[C2:.+]] = llvm.mlir.constant(78 : i32) : i32
456; CHECK: %[[C3:.+]] = llvm.mlir.constant(94 : i32) : i32
457; CHECK: %[[C4:.+]] = llvm.mlir.constant(1 : i32) : i32
458; CHECK: llvm.switch %arg0 : i32, ^[[BB5:.+]] [
459; CHECK:   0: ^[[BB1:.+]],
460; CHECK:   9: ^[[BB2:.+]],
461; CHECK:   994: ^[[BB3:.+]],
462; CHECK:   1154: ^[[BB4:.+]]
463; CHECK: ]
464  switch i32 %val, label %def [
465    i32 0, label %one
466    i32 9, label %two
467    i32 994, label %three
468    i32 1154, label %four
469  ]
470
471; CHECK: ^[[BB1]]:
472; CHECK: llvm.call @g(%[[C4]]) : (i32) -> ()
473; CHECK: llvm.return
474one:
475  call void @g(i32 1)
476  ret void
477; CHECK: ^[[BB2]]:
478; CHECK: llvm.call @g(%[[C3]]) : (i32) -> ()
479; CHECK: llvm.return
480two:
481  call void @g(i32 94)
482  ret void
483; CHECK: ^[[BB3]]:
484; CHECK: llvm.call @g(%[[C2]]) : (i32) -> ()
485; CHECK: llvm.return
486three:
487  call void @g(i32 78)
488  ret void
489; CHECK: ^[[BB4]]:
490; CHECK: llvm.call @g(%[[C1]]) : (i32) -> ()
491; CHECK: llvm.return
492four:
493  call void @g(i32 87)
494  ret void
495; CHECK: ^[[BB5]]:
496; CHECK: llvm.call @g(%[[C0]]) : (i32) -> ()
497; CHECK: llvm.return
498def:
499  call void @g(i32 11)
500  ret void
501}
502
503; CHECK-LABEL: llvm.func @switch_args(%arg0: i32) {
504define void @switch_args(i32 %val) {
505  ; CHECK: %[[C0:.+]] = llvm.mlir.constant(44 : i32) : i32
506  ; CHECK: %[[C1:.+]] = llvm.mlir.constant(34 : i32) : i32
507  ; CHECK: %[[C2:.+]] = llvm.mlir.constant(33 : i32) : i32
508  %pred = icmp ult i32 %val, 87
509  br i1 %pred, label %bbs, label %bb1
510
511bb1:
512  %vx = add i32 %val, 22
513  %pred2 = icmp ult i32 %val, 94
514  br i1 %pred2, label %bb2, label %bb3
515
516bb2:
517  %vx0 = add i32 %val, 23
518  br label %one
519
520bb3:
521  br label %def
522
523; CHECK: %[[V1:.+]] = llvm.add %arg0, %[[C2]] : i32
524; CHECK: %[[V2:.+]] = llvm.add %arg0, %[[C1]] : i32
525; CHECK: %[[V3:.+]] = llvm.add %arg0, %[[C0]] : i32
526; CHECK: llvm.switch %arg0 : i32, ^[[BBD:.+]](%[[V3]] : i32) [
527; CHECK:   0: ^[[BB1:.+]](%[[V1]], %[[V2]] : i32, i32)
528; CHECK: ]
529bbs:
530  %vy = add i32 %val, 33
531  %vy0 = add i32 %val, 34
532  %vz = add i32 %val, 44
533  switch i32 %val, label %def [
534    i32 0, label %one
535  ]
536
537; CHECK: ^[[BB1]](%[[BA0:.+]]: i32, %[[BA1:.+]]: i32):
538one: ; pred: bb2, bbs
539  %v0 = phi i32 [%vx, %bb2], [%vy, %bbs]
540  %v1 = phi i32 [%vx0, %bb2], [%vy0, %bbs]
541  ; CHECK: llvm.add %[[BA0]], %[[BA1]]  : i32
542  %vf = add i32 %v0, %v1
543  call void @g(i32 %vf)
544  ret void
545
546; CHECK: ^[[BBD]](%[[BA2:.+]]: i32):
547def: ; pred: bb3, bbs
548  %v2 = phi i32 [%vx, %bb3], [%vz, %bbs]
549  ; CHECK: llvm.call @g(%[[BA2]])
550  call void @g(i32 %v2)
551  ret void
552}
553
554; Insert/ExtractValue
555; CHECK-LABEL: llvm.func @insert_extract_value_struct
556define float @insert_extract_value_struct({{i32},{float, double}}* %p) {
557  ; CHECK: %[[C0:.+]] = llvm.mlir.constant(2.000000e+00 : f64)
558  ; CHECK: %[[VT:.+]] = llvm.load %{{.+}}
559  %t = load {{i32},{float, double}}, {{i32},{float, double}}* %p
560  ; CHECK: %[[EV:.+]] = llvm.extractvalue %[[VT]][1 : i32, 0 : i32] :
561  ; CHECK-SAME: !llvm.struct<(struct<(i32)>, struct<(f32, f64)>)>
562  %s = extractvalue {{i32},{float, double}} %t, 1, 0
563  ; CHECK: %[[IV:.+]] = llvm.insertvalue %[[C0]], %[[VT]][1 : i32, 1 : i32] :
564  ; CHECK-SAME: !llvm.struct<(struct<(i32)>, struct<(f32, f64)>)>
565  %r = insertvalue {{i32},{float, double}} %t, double 2.0, 1, 1
566  ; CHECK: llvm.store %[[IV]], %{{.+}}
567  store {{i32},{float, double}} %r, {{i32},{float, double}}* %p
568  ; CHECK: llvm.return %[[EV]]
569  ret float %s
570}
571
572; CHECK-LABEL: llvm.func @insert_extract_value_array
573define void @insert_extract_value_array([4 x [4 x i8]] %x1) {
574  ; CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i8)
575  ; CHECK: llvm.insertvalue %[[C0]], %{{.+}}[0 : i32, 0 : i32] : !llvm.array<4 x array<4 x i8>>
576  %res1 = insertvalue [4 x [4 x i8 ]] %x1, i8 0, 0, 0
577  ; CHECK: llvm.extractvalue %{{.+}}[1 : i32] : !llvm.array<4 x array<4 x i8>>
578  %res2 = extractvalue [4 x [4 x i8 ]] %x1, 1
579  ; CHECK: llvm.extractvalue %{{.+}}[0 : i32, 1 : i32] : !llvm.array<4 x array<4 x i8>>
580  %res3 = extractvalue [4 x [4 x i8 ]] %x1, 0, 1
581  ret void
582}
583
584; Shufflevector
585; CHECK-LABEL: llvm.func @shuffle_vec
586define <4 x half> @shuffle_vec(<4 x half>* %arg0, <4 x half>* %arg1) {
587  ; CHECK: %[[V0:.+]] = llvm.load %{{.+}} : !llvm.ptr<vector<4xf16>>
588  %val0 = load <4 x half>, <4 x half>* %arg0
589  ; CHECK: %[[V1:.+]] = llvm.load %{{.+}} : !llvm.ptr<vector<4xf16>>
590  %val1 = load <4 x half>, <4 x half>* %arg1
591  ; CHECK: llvm.shufflevector %[[V0]], %[[V1]] [2 : i32, 3 : i32, -1 : i32, -1 : i32] : vector<4xf16>, vector<4xf16>
592  %shuffle = shufflevector <4 x half> %val0, <4 x half> %val1, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
593  ret <4 x half> %shuffle
594}
595
596; ExtractElement
597; CHECK-LABEL: llvm.func @extract_element
598define half @extract_element(<4 x half>* %vec, i32 %idx) {
599  ; CHECK: %[[V0:.+]] = llvm.load %{{.+}} : !llvm.ptr<vector<4xf16>>
600  %val0 = load <4 x half>, <4 x half>* %vec
601  ; CHECK: %[[V1:.+]] = llvm.extractelement %[[V0]][%{{.+}} : i32] : vector<4xf16>
602  %r = extractelement <4 x half> %val0, i32 %idx
603  ; CHECK: llvm.return %[[V1]]
604  ret half %r
605}
606
607; InsertElement
608; CHECK-LABEL: llvm.func @insert_element
609define <4 x half> @insert_element(<4 x half>* %vec, half %v, i32 %idx) {
610  ; CHECK: %[[V0:.+]] = llvm.load %{{.+}} : !llvm.ptr<vector<4xf16>>
611  %val0 = load <4 x half>, <4 x half>* %vec
612  ; CHECK: %[[V1:.+]] = llvm.insertelement %{{.+}}, %[[V0]][%{{.+}} : i32] : vector<4xf16>
613  %r = insertelement <4 x half> %val0, half %v, i32 %idx
614  ; CHECK: llvm.return %[[V1]]
615  ret <4 x half> %r
616}
617
618; Select
619; CHECK-LABEL: llvm.func @select_inst
620define void @select_inst(i32 %arg0, i32 %arg1, i1 %pred) {
621  ; CHECK: %{{.+}} = llvm.select %{{.+}}, %{{.+}}, %{{.+}} : i1, i32
622  %1 = select i1 %pred, i32 %arg0, i32 %arg1
623  ret void
624}
625
626; Unreachable
627; CHECK-LABEL: llvm.func @unreachable_inst
628define void @unreachable_inst() {
629  ; CHECK: llvm.unreachable
630  unreachable
631}
632
633; Varadic function definition
634%struct.va_list = type { i8* }
635
636declare void @llvm.va_start(i8*)
637declare void @llvm.va_copy(i8*, i8*)
638declare void @llvm.va_end(i8*)
639
640; CHECK-LABEL: llvm.func @variadic_function
641define void @variadic_function(i32 %X, ...) {
642  ; CHECK: %[[ALLOCA0:.+]] = llvm.alloca %{{.*}} x !llvm.struct<"struct.va_list", (ptr<i8>)> {{.*}} : (i32) -> !llvm.ptr<struct<"struct.va_list", (ptr<i8>)>>
643  %ap = alloca %struct.va_list
644  ; CHECK: %[[CAST0:.+]] = llvm.bitcast %[[ALLOCA0]] : !llvm.ptr<struct<"struct.va_list", (ptr<i8>)>> to !llvm.ptr<i8>
645  %ap2 = bitcast %struct.va_list* %ap to i8*
646  ; CHECK: llvm.intr.vastart %[[CAST0]]
647  call void @llvm.va_start(i8* %ap2)
648
649  ; CHECK: %[[ALLOCA1:.+]] = llvm.alloca %{{.*}} x !llvm.ptr<i8> {{.*}} : (i32) -> !llvm.ptr<ptr<i8>>
650  %aq = alloca i8*
651  ; CHECK: %[[CAST1:.+]] = llvm.bitcast %[[ALLOCA1]] : !llvm.ptr<ptr<i8>> to !llvm.ptr<i8>
652  %aq2 = bitcast i8** %aq to i8*
653  ; CHECK: llvm.intr.vacopy %[[CAST0]] to %[[CAST1]]
654  call void @llvm.va_copy(i8* %aq2, i8* %ap2)
655  ; CHECK: llvm.intr.vaend %[[CAST1]]
656  call void @llvm.va_end(i8* %aq2)
657
658  ; CHECK: llvm.intr.vaend %[[CAST0]]
659  call void @llvm.va_end(i8* %ap2)
660  ; CHECK: llvm.return
661  ret void
662}
663