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