1; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s 2 3; CHECK-LABEL: @int_constants 4define void @int_constants(i16 %arg0, i32 %arg1, i1 %arg2) { 5 ; CHECK: %[[C0:.+]] = llvm.mlir.constant(42 : i16) : i16 6 ; CHECK: %[[C1:.+]] = llvm.mlir.constant(7 : i32) : i32 7 ; CHECK: %[[C2:.+]] = llvm.mlir.constant(true) : i1 8 9 ; CHECK: llvm.add %[[C0]], %{{.*}} : i16 10 %1 = add i16 42, %arg0 11 ; CHECK: llvm.add %[[C1]], %{{.*}} : i32 12 %2 = add i32 7, %arg1 13 ; CHECK: llvm.or %[[C2]], %{{.*}} : i1 14 %3 = or i1 1, %arg2 15 ret void 16} 17 18; // ----- 19 20; CHECK-LABEL: @float_constants 21define void @float_constants(half %arg0, bfloat %arg1, fp128 %arg2, x86_fp80 %arg3) { 22 ; CHECK: %[[C0:.+]] = llvm.mlir.constant(1.000000e+00 : f16) : f16 23 ; CHECK: %[[C1:.+]] = llvm.mlir.constant(1.000000e+00 : bf16) : bf16 24 ; CHECK: %[[C2:.+]] = llvm.mlir.constant(0.000000e+00 : f128) : f128 25 ; CHECK: %[[C3:.+]] = llvm.mlir.constant(7.000000e+00 : f80) : f80 26 27 ; CHECK: llvm.fadd %[[C0]], %{{.*}} : f16 28 %1 = fadd half 1.0, %arg0 29 ; CHECK: llvm.fadd %[[C1]], %{{.*}} : bf16 30 %2 = fadd bfloat 1.0, %arg1 31 ; CHECK: llvm.fadd %[[C2]], %{{.*}} : f128 32 %3 = fadd fp128 0xL00000000000000000000000000000000, %arg2 33 ; CHECK: llvm.fadd %[[C3]], %{{.*}} : f80 34 %4 = fadd x86_fp80 0xK4001E000000000000000, %arg3 35 ret void 36} 37 38; // ----- 39 40; CHECK-LABEL: @undef_constant 41define void @undef_constant(i32 %arg0) { 42 ; CHECK: %[[UNDEF:.+]] = llvm.mlir.undef : i32 43 ; CHECK: llvm.add %[[UNDEF]], %{{.*}} : i32 44 %1 = add i32 undef, %arg0 45 ret void 46} 47 48; // ----- 49 50; CHECK-LABEL: @poison_constant 51define void @poison_constant(double %arg0) { 52 ; CHECK: %[[POISON:.+]] = llvm.mlir.poison : f64 53 ; CHECK: llvm.fadd %[[POISON]], %{{.*}} : f64 54 %1 = fadd double poison, %arg0 55 ret void 56} 57 58; // ----- 59 60; CHECK-LABEL: @null_constant 61define ptr @null_constant() { 62 ; CHECK: %[[NULL:[0-9]+]] = llvm.mlir.zero : !llvm.ptr 63 ; CHECK: llvm.return %[[NULL]] : !llvm.ptr 64 ret ptr null 65} 66 67; // ----- 68 69@global = external global i32, align 8 70 71; CHECK-LABEL: @gep_const_expr 72define ptr @gep_const_expr() { 73 ; CHECK-DAG: %[[ADDR:[0-9]+]] = llvm.mlir.addressof @global : !llvm.ptr 74 ; CHECK-DAG: %[[IDX:[0-9]+]] = llvm.mlir.constant(2 : i32) : i32 75 ; CHECK-DAG: %[[GEP:[0-9]+]] = llvm.getelementptr %[[ADDR]][%[[IDX]]] : (!llvm.ptr, i32) -> !llvm.ptr 76 ; CHECK-DAG: llvm.return %[[GEP]] : !llvm.ptr 77 ret ptr getelementptr (i32, ptr @global, i32 2) 78} 79 80; // ----- 81 82@global = external global i32, align 8 83 84; CHECK-LABEL: @const_expr_with_duplicate 85define i64 @const_expr_with_duplicate() { 86 ; CHECK-DAG: %[[ADDR:[0-9]+]] = llvm.mlir.addressof @global : !llvm.ptr 87 ; CHECK-DAG: %[[IDX:[0-9]+]] = llvm.mlir.constant(7 : i32) : i32 88 ; CHECK-DAG: %[[GEP:[0-9]+]] = llvm.getelementptr %[[ADDR]][%[[IDX]]] : (!llvm.ptr, i32) -> !llvm.ptr 89 ; CHECK-DAG: %[[DUP:[0-9]+]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 90 91 ; Verify the duplicate sub expression is converted only once. 92 ; CHECK-DAG: %[[SUM:[0-9]+]] = llvm.add %[[DUP]], %[[DUP]] : i64 93 ; CHECK-DAG: llvm.return %[[SUM]] : i64 94 ret i64 add (i64 ptrtoint (ptr getelementptr (i32, ptr @global, i32 7) to i64), 95 i64 ptrtoint (ptr getelementptr (i32, ptr @global, i32 7) to i64)) 96} 97 98; // ----- 99 100@global = external global i32, align 8 101 102; CHECK-LABEL: @const_expr_with_aggregate() 103define i64 @const_expr_with_aggregate() { 104 ; Compute the vector elements. 105 ; CHECK-DAG: %[[VAL1:[0-9]+]] = llvm.mlir.constant(33 : i64) : i64 106 ; CHECK-DAG: %[[ADDR:[0-9]+]] = llvm.mlir.addressof @global : !llvm.ptr 107 ; CHECK-DAG: %[[IDX1:[0-9]+]] = llvm.mlir.constant(7 : i32) : i32 108 ; CHECK-DAG: %[[GEP1:[0-9]+]] = llvm.getelementptr %[[ADDR]][%[[IDX1]]] : (!llvm.ptr, i32) -> !llvm.ptr 109 ; CHECK-DAG: %[[VAL2:[0-9]+]] = llvm.ptrtoint %[[GEP1]] : !llvm.ptr to i64 110 111 ; Fill the vector. 112 ; CHECK-DAG: %[[VEC1:[0-9]+]] = llvm.mlir.undef : vector<2xi64> 113 ; CHECK-DAG: %[[IDX2:[0-9]+]] = llvm.mlir.constant(0 : i32) : i32 114 ; CHECK-DAG: %[[VEC2:[0-9]+]] = llvm.insertelement %[[VAL1]], %[[VEC1]][%[[IDX2]] : i32] : vector<2xi64> 115 ; CHECK-DAG: %[[IDX3:[0-9]+]] = llvm.mlir.constant(1 : i32) : i32 116 ; CHECK-DAG: %[[VEC3:[0-9]+]] = llvm.insertelement %[[VAL2]], %[[VEC2]][%[[IDX3]] : i32] : vector<2xi64> 117 ; CHECK-DAG: %[[IDX4:[0-9]+]] = llvm.mlir.constant(42 : i32) : i32 118 119 ; Compute the extract index. 120 ; CHECK-DAG: %[[GEP2:[0-9]+]] = llvm.getelementptr %[[ADDR]][%[[IDX4]]] : (!llvm.ptr, i32) -> !llvm.ptr 121 ; CHECK-DAG: %[[IDX5:[0-9]+]] = llvm.ptrtoint %[[GEP2]] : !llvm.ptr to i64 122 123 ; Extract the vector element. 124 ; CHECK-DAG: %[[ELEM:[0-9]+]] = llvm.extractelement %[[VEC3]][%[[IDX5]] : i64] : vector<2xi64> 125 ; CHECK-DAG: llvm.return %[[ELEM]] : i64 126 ret i64 extractelement ( 127 <2 x i64> <i64 33, i64 ptrtoint (ptr getelementptr (i32, ptr @global, i32 7) to i64)>, 128 i64 ptrtoint (ptr getelementptr (i32, ptr @global, i32 42) to i64)) 129} 130 131; // ----- 132 133; Verify the function constant import. 134 135; Calling a function that has not been defined yet. 136; CHECK-LABEL: @function_address_before_def 137define i32 @function_address_before_def() { 138 %1 = alloca ptr 139 ; CHECK: %[[FUN:.*]] = llvm.mlir.addressof @callee : !llvm.ptr 140 ; CHECK: llvm.store %[[FUN]], %[[PTR:.*]] : !llvm.ptr, !llvm.ptr 141 store ptr @callee, ptr %1 142 ; CHECK: %[[INDIR:.*]] = llvm.load %[[PTR]] : !llvm.ptr -> !llvm.ptr 143 %2 = load ptr, ptr %1 144 ; CHECK: llvm.call %[[INDIR]]() : !llvm.ptr, () -> i32 145 %3 = call i32 %2() 146 ret i32 %3 147} 148 149define i32 @callee() { 150 ret i32 42 151} 152 153; Calling a function that has been defined. 154; CHECK-LABEL: @function_address_after_def 155define i32 @function_address_after_def() { 156 %1 = alloca ptr 157 ; CHECK: %[[FUN:.*]] = llvm.mlir.addressof @callee : !llvm.ptr 158 ; CHECK: llvm.store %[[FUN]], %[[PTR:.*]] : !llvm.ptr, !llvm.ptr 159 store ptr @callee, ptr %1 160 ; CHECK: %[[INDIR:.*]] = llvm.load %[[PTR]] : !llvm.ptr -> !llvm.ptr 161 %2 = load ptr, ptr %1 162 ; CHECK: llvm.call %[[INDIR]]() : !llvm.ptr, () -> i32 163 %3 = call i32 %2() 164 ret i32 %3 165} 166 167; // ----- 168 169; Verify the aggregate constant import. 170 171; CHECK-DAG: %[[C0:.+]] = llvm.mlir.constant(9 : i32) : i32 172; CHECK-DAG: %[[C1:.+]] = llvm.mlir.constant(4 : i8) : i8 173; CHECK-DAG: %[[C2:.+]] = llvm.mlir.constant(8 : i16) : i16 174; CHECK-DAG: %[[C3:.+]] = llvm.mlir.constant(7 : i32) : i32 175; CHECK-DAG: %[[ROOT:.+]] = llvm.mlir.undef : !llvm.struct<"simple_agg_type", (i32, i8, i16, i32)> 176; CHECK-DAG: %[[CHAIN0:.+]] = llvm.insertvalue %[[C0]], %[[ROOT]][0] 177; CHECK-DAG: %[[CHAIN1:.+]] = llvm.insertvalue %[[C1]], %[[CHAIN0]][1] 178; CHECK-DAG: %[[CHAIN2:.+]] = llvm.insertvalue %[[C2]], %[[CHAIN1]][2] 179; CHECK-DAG: %[[CHAIN3:.+]] = llvm.insertvalue %[[C3]], %[[CHAIN2]][3] 180; CHECK-DAG: llvm.return %[[CHAIN3]] 181%simple_agg_type = type {i32, i8, i16, i32} 182@simple_agg = global %simple_agg_type {i32 9, i8 4, i16 8, i32 7} 183 184; CHECK-DAG: %[[C1:.+]] = llvm.mlir.constant(1 : i32) : i32 185; CHECK-DAG: %[[C2:.+]] = llvm.mlir.constant(2 : i8) : i8 186; CHECK-DAG: %[[C3:.+]] = llvm.mlir.constant(3 : i16) : i16 187; CHECK-DAG: %[[C4:.+]] = llvm.mlir.constant(4 : i32) : i32 188; CHECK-DAG: %[[NESTED:.+]] = llvm.mlir.undef : !llvm.struct<"simple_agg_type", (i32, i8, i16, i32)> 189; CHECK-DAG: %[[CHAIN0:.+]] = llvm.insertvalue %[[C1]], %[[NESTED]][0] 190; CHECK-DAG: %[[CHAIN1:.+]] = llvm.insertvalue %[[C2]], %[[CHAIN0]][1] 191; CHECK-DAG: %[[CHAIN2:.+]] = llvm.insertvalue %[[C3]], %[[CHAIN1]][2] 192; CHECK-DAG: %[[CHAIN3:.+]] = llvm.insertvalue %[[C4]], %[[CHAIN2]][3] 193; CHECK-DAG: %[[NULL:.+]] = llvm.mlir.zero : !llvm.ptr 194; CHECK-DAG: %[[ROOT:.+]] = llvm.mlir.undef : !llvm.struct<"nested_agg_type", (struct<"simple_agg_type", (i32, i8, i16, i32)>, ptr)> 195; CHECK-DAG: %[[CHAIN4:.+]] = llvm.insertvalue %[[CHAIN3]], %[[ROOT]][0] 196; CHECK-DAG: %[[CHAIN5:.+]] = llvm.insertvalue %[[NULL]], %[[CHAIN4]][1] 197; CHECK-DAG: llvm.return %[[CHAIN5]] 198%nested_agg_type = type {%simple_agg_type, ptr} 199@nested_agg = global %nested_agg_type { %simple_agg_type{i32 1, i8 2, i16 3, i32 4}, ptr null } 200 201; CHECK-DAG: %[[NULL:.+]] = llvm.mlir.zero : !llvm.ptr 202; CHECK-DAG: %[[ROOT:.+]] = llvm.mlir.undef : !llvm.vec<2 x ptr> 203; CHECK-DAG: %[[P0:.+]] = llvm.mlir.constant(0 : i32) : i32 204; CHECK-DAG: %[[CHAIN0:.+]] = llvm.insertelement %[[NULL]], %[[ROOT]][%[[P0]] : i32] : !llvm.vec<2 x ptr> 205; CHECK-DAG: %[[P1:.+]] = llvm.mlir.constant(1 : i32) : i32 206; CHECK-DAG: %[[CHAIN1:.+]] = llvm.insertelement %[[NULL]], %[[CHAIN0]][%[[P1]] : i32] : !llvm.vec<2 x ptr> 207; CHECK-DAG: llvm.return %[[CHAIN1]] : !llvm.vec<2 x ptr> 208@vector_agg = global <2 x ptr> <ptr null, ptr null> 209 210; // ----- 211 212; Verfiy the import of subsequent constant expressions with duplicates. 213 214@global = external global i32, align 8 215 216; CHECK-LABEL: @const_exprs_with_duplicate 217define i64 @const_exprs_with_duplicate() { 218 ; CHECK: %[[ADDR:.+]] = llvm.mlir.addressof @global : !llvm.ptr 219 ; CHECK: llvm.getelementptr %[[ADDR]][%{{.*}}] : (!llvm.ptr, i32) -> !llvm.ptr 220 %1 = add i64 1, ptrtoint (ptr getelementptr (i32, ptr @global, i32 7) to i64) 221 222 ; Verify the address value is reused. 223 ; CHECK: llvm.getelementptr %[[ADDR]][%{{.*}}] : (!llvm.ptr, i32) -> !llvm.ptr 224 %2 = add i64 %1, ptrtoint (ptr getelementptr (i32, ptr @global, i32 42) to i64) 225 ret i64 %2 226} 227 228; // ----- 229 230; Verify the import of constant expressions with cyclic dependencies. 231 232@cyclic = internal constant i64 add (i64 ptrtoint (ptr @cyclic to i64), i64 ptrtoint (ptr @cyclic to i64)) 233 234; CHECK-LABEL: @cyclic 235; CHECK: %[[ADDR:.+]] = llvm.mlir.addressof @cyclic 236; CHECK: %[[VAL0:.+]] = llvm.ptrtoint %[[ADDR]] 237; CHECK: %[[VAL1:.+]] = llvm.add %[[VAL0]], %[[VAL0]] 238; CHECK: llvm.return %[[VAL1]] 239