Auto merge of #28079 - huonw:simd, r=alexcrichton
This adds a new Python script (compatible with 2.7 and 3.x) that will consume some JSON files that define a platform's intrinsics. It can output a file that defines the intrinsics in the compiler, or an `extern` block that will import them. The complexity of the generator is to be DRY: platforms (especially ARM and AArch64) have a lot of repetition with their intrinsics, for different versions with different types, so being able to write it once is nice.
This commit is contained in:
commit
2d3e8379c8
550
src/etc/platform-intrinsics/aarch64.json
Normal file
550
src/etc/platform-intrinsics/aarch64.json
Normal file
@ -0,0 +1,550 @@
|
||||
{
|
||||
"platform": "aarch64",
|
||||
"intrinsic_prefix": "aarch64_v",
|
||||
"llvm_prefix": "llvm.aarch64.neon.",
|
||||
"number_info": {
|
||||
"signed": {
|
||||
"kind": "s",
|
||||
"data_type": { "pattern": "s{bitwidth}" }
|
||||
},
|
||||
"unsigned": {
|
||||
"kind": "u",
|
||||
"data_type": { "pattern": "u{bitwidth}" }
|
||||
},
|
||||
"float": {
|
||||
"kind": "f",
|
||||
"data_type": { "pattern": "f{bitwidth}" }
|
||||
}
|
||||
},
|
||||
"width_info": {
|
||||
"64": { "width": "" },
|
||||
"128": { "width": "q" }
|
||||
},
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "hadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}hadd.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rhadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}rhadd.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}qadd.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "uqadd_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "suqadd.{0.llvm_name}",
|
||||
"ret": "s(8-64)",
|
||||
"args": ["0", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sqadd_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "usqadd.{0.llvm_name}",
|
||||
"ret": "u(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "raddhn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "raddhn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "fmulx{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "fmulx.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "fma{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.fma.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qdmulh{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqdmulh.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqrdmulh.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "mull_{1.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}mull.{0.llvm_name}",
|
||||
"ret": "i(16-64)",
|
||||
"args": ["0n", "0n"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qdmull{0.width}_{1.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "sqdmull.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0n", "0n"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "hsub{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}hsub.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qsub{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}qsub.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsubhn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "rsubhn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abd{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}abd.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f(32-64)"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "max{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}max.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f(32-64)"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "min{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}min.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f(32-64)"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "maxnm{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}maxnm.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "minnm{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}minnm.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "shl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}shl.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}qshl.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}rshl.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}qrshl.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshrun_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "sqshrun.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshrun_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "sqrshrun.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "{0.kind}qshrn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "rshrn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "{0.kind}qrshrn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sri{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "vsri.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sli{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "vsli.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "vqmovn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "{0.kind}qxtn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abs{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "abs.{0.llvm_name}",
|
||||
"ret": "s(8-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abs{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.fabs.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qabs{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "sqabs.{0.llvm_name}",
|
||||
"ret": "s(8-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qneg{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqneg.{0.llvm_name}",
|
||||
"ret": "s(8-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "clz{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.ctlz.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "cls{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "cls.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "cnt{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.ctpop.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "recpe{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}recpe.{0.llvm_name}",
|
||||
"ret": ["u32","f(32-64)"],
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "recps{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "frecps.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sqrt{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.sqrt.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsqrte{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}rsqrte.{0.llvm_name}",
|
||||
"ret": ["u32","f(32-64)"],
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsqrts{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "frsqrts.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rbit{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "rbit.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "padd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "addp.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "padd{0.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "addp.{0.llvm_name}",
|
||||
"ret": ["i64","f64"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "paddl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}addlp.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "i(16-64)",
|
||||
"args": ["0dn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmax{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}maxp.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmax{0.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}maxp.{0.llvm_name}",
|
||||
"ret": ["i64","f64"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmin{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}minp.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmin{0.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}minp.{0.llvm_name}",
|
||||
"ret": ["i64","f64"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
|
||||
"ret": ["i64","f64"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pminnm{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}minnmp.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pminnm{0.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}minnmp.{0.llvm_name}",
|
||||
"ret": "f64",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "addv{1.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": ["I(8-32)","F32"],
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "addv{1.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": ["I64","F64"],
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "addlv{1.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}addlv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "I(16-64)",
|
||||
"args": ["0vdn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "maxv{1.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": ["I(8-32)","F32"],
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "maxv{1.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F64",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "minv{1.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": ["I(8-32)","F32"],
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "minv{1.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F64",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "maxnmv{1.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F32",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "maxnmv{1.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F64",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "minnmv{1.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F32",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "minnmv{1.width}_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "F64",
|
||||
"args": ["0v"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbl1{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbl1.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0x128", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbx1{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbx1.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0", "0x128", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbl2{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbl2.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["(0x128,0x128)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbx2{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbx2.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["(0x128,0x128)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbl3{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbl3.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["(0x128,0x128,0x128)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbx3{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbx3.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0", "(0x128,0x128,0x128)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbl4{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbl4.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["(0x128,0x128,0x128,0x128)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qtbx4{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "tbx4.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0", "(0x128,0x128,0x128,0x128)f", "0u"]
|
||||
}
|
||||
]
|
||||
}
|
396
src/etc/platform-intrinsics/arm.json
Normal file
396
src/etc/platform-intrinsics/arm.json
Normal file
@ -0,0 +1,396 @@
|
||||
{
|
||||
"platform": "arm",
|
||||
"intrinsic_prefix": "arm_v",
|
||||
"llvm_prefix": "llvm.neon.v",
|
||||
"number_info": {
|
||||
"signed": {
|
||||
"kind": "s",
|
||||
"data_type": { "pattern": "s{bitwidth}" }
|
||||
},
|
||||
"unsigned": {
|
||||
"kind": "u",
|
||||
"data_type": { "pattern": "u{bitwidth}" }
|
||||
},
|
||||
"float": {
|
||||
"kind": "f",
|
||||
"data_type": { "pattern": "f{bitwidth}" }
|
||||
}
|
||||
},
|
||||
"width_info": {
|
||||
"64": { "width": "" },
|
||||
"128": { "width": "q" }
|
||||
},
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "hadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "hadd{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rhadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "rhadd{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qadd{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "qadd{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "raddhn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "raddhn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "fma{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.fma.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qdmulh{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqdmulh.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqrdmulh.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "mull_{1.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "mull{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(16-64)",
|
||||
"args": ["0n", "0n"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qdmull{0.width}_{1.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "sqdmull.{0.llvm_name}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0n", "0n"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "hsub{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "hsub{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qsub{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "qsub{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsubhn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "rsubhn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abd{0.width}_{1.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "abd{0.kind}.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "max{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "max{0.kind}.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "min{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "min{0.kind}.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "shl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "shl{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "qshl{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "rshl{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "qrshl{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshrun_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "sqshrun.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshrun_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "sqrshrun.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "qshrn{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "rshrn.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qrshrn_n_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "qrshrn{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w", "U32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sri{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "vsri.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sli{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "vsli.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "vqmovn_{1.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "qxtn{0.kind}.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0w"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abs{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "abs.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "abs{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.fabs.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qabs{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "sqabs.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "qneg{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "sqneg.{0.llvm_name}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "clz{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.ctlz.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "cls{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "cls.{0.llvm_name}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "cnt{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.ctpop.{0.llvm_name}",
|
||||
"ret": "i8",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "recpe{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "recpe.{0.llvm_name}",
|
||||
"ret": ["u32","f32"],
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "recps{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "frecps.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "sqrt{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "!llvm.sqrt.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsqrte{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "rsqrte.{0.llvm_name}",
|
||||
"ret": ["u32","f32"],
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "rsqrts{0.width}_{0.data_type}",
|
||||
"width": [64,128],
|
||||
"llvm": "rsqrts.{0.llvm_name}",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "bsl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "bsl.{0.llvm_name}",
|
||||
"ret": "i(8-64)",
|
||||
"args": ["0u", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "padd{0.width}_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "padd.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "paddl{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "paddl{0.kind}.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "i(16-64)",
|
||||
"args": ["0dn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "padal{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "padal{0.kind}.{0.llvm_name}.{1.llvm_name}",
|
||||
"ret": "i(16-64)",
|
||||
"args": ["0", "0dn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmax{0.width}_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "pmax{0.kind}.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "pmin{0.width}_{0.data_type}",
|
||||
"width": [64, 128],
|
||||
"llvm": "pmin{0.kind}.{0.llvm_name}",
|
||||
"ret": ["i(8-32)","f32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbl1_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbl1",
|
||||
"ret": "i8",
|
||||
"args": ["0", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbx1_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbx1",
|
||||
"ret": "i8",
|
||||
"args": ["0", "0", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbl2_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbl2",
|
||||
"ret": "i8",
|
||||
"args": ["(0,0)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbx2_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbx2",
|
||||
"ret": "i8",
|
||||
"args": ["(0,0)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbl3_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbl3",
|
||||
"ret": "i8",
|
||||
"args": ["(0,0,0)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbx3_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbx3",
|
||||
"ret": "i8",
|
||||
"args": ["0", "(0,0,0)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbl4_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbl4",
|
||||
"ret": "i8",
|
||||
"args": ["(0,0,0,0)f", "0u"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "tbx4_{0.data_type}",
|
||||
"width": [64],
|
||||
"llvm": "tbx4",
|
||||
"ret": "i8",
|
||||
"args": ["0", "(0,0,0,0)f", "0u"]
|
||||
}
|
||||
]
|
||||
}
|
571
src/etc/platform-intrinsics/generator.py
Normal file
571
src/etc/platform-intrinsics/generator.py
Normal file
@ -0,0 +1,571 @@
|
||||
# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
# file at the top-level directory of this distribution and at
|
||||
# http://rust-lang.org/COPYRIGHT.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
# option. This file may not be copied, modified, or distributed
|
||||
# except according to those terms.
|
||||
|
||||
from __future__ import division, print_function
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
import re
|
||||
import textwrap
|
||||
|
||||
SPEC = re.compile(
|
||||
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
|
||||
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
|
||||
r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
|
||||
)
|
||||
|
||||
class PlatformInfo(object):
|
||||
def __init__(self, json):
|
||||
self._platform = json['platform']
|
||||
self._intrinsic_prefix = json['intrinsic_prefix']
|
||||
|
||||
def intrinsic_prefix(self):
|
||||
return self._intrinsic_prefix
|
||||
|
||||
class IntrinsicSet(object):
|
||||
def __init__(self, platform, json):
|
||||
self._llvm_prefix = json['llvm_prefix']
|
||||
self._type_info = json['number_info']
|
||||
self._intrinsics = json['intrinsics']
|
||||
self._widths = json['width_info']
|
||||
self._platform = platform
|
||||
|
||||
def intrinsics(self):
|
||||
for raw in self._intrinsics:
|
||||
yield GenericIntrinsic(self,
|
||||
raw['intrinsic'], raw['width'], raw['llvm'],
|
||||
raw['ret'], raw['args'])
|
||||
|
||||
def platform(self):
|
||||
return self._platform
|
||||
|
||||
def llvm_prefix(self):
|
||||
return self._llvm_prefix
|
||||
|
||||
def width_info(self, bitwidth):
|
||||
return self._widths[str(bitwidth)]
|
||||
|
||||
def number_type_info(self, value):
|
||||
data = self._type_info[value.__class__.__name__.lower()]
|
||||
bitwidth = value.bitwidth()
|
||||
def lookup(raw):
|
||||
if not isinstance(raw, dict):
|
||||
return raw
|
||||
|
||||
try:
|
||||
return raw[str(bitwidth)]
|
||||
except KeyError:
|
||||
return raw['pattern'].format(bitwidth = bitwidth)
|
||||
|
||||
return PlatformTypeInfo(value.llvm_name(),
|
||||
{k: lookup(v) for k, v in data.items()})
|
||||
|
||||
class PlatformTypeInfo(object):
|
||||
def __init__(self, llvm_name, properties):
|
||||
self.properties = properties
|
||||
self.llvm_name = llvm_name
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.properties[name]
|
||||
|
||||
def vectorize(self, length, width_info):
|
||||
props = self.properties.copy()
|
||||
props.update(width_info)
|
||||
return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props)
|
||||
|
||||
class Type(object):
|
||||
def __init__(self, bitwidth):
|
||||
self._bitwidth = bitwidth
|
||||
|
||||
def bitwidth(self):
|
||||
return self._bitwidth
|
||||
|
||||
def modify(self, spec, width):
|
||||
raise NotImplementedError()
|
||||
|
||||
class Number(Type):
|
||||
def __init__(self, bitwidth):
|
||||
Type.__init__(self, bitwidth)
|
||||
|
||||
def modify(self, spec, width):
|
||||
if spec == 'u':
|
||||
return Unsigned(self.bitwidth())
|
||||
elif spec == 's':
|
||||
return Signed(self.bitwidth())
|
||||
elif spec == 'w':
|
||||
return self.__class__(self.bitwidth() * 2)
|
||||
elif spec == 'n':
|
||||
return self.__class__(self.bitwidth() // 2)
|
||||
elif spec == 'v':
|
||||
return Vector(self, width // self.bitwidth())
|
||||
else:
|
||||
raise ValueError('unknown modification spec {}', spec)
|
||||
|
||||
def type_info(self, platform_info):
|
||||
return platform_info.number_type_info(self)
|
||||
|
||||
class Signed(Number):
|
||||
def __init__(self, bitwidth, llvm_bitwidth = None):
|
||||
Number.__init__(self, bitwidth)
|
||||
self._llvm_bitwidth = llvm_bitwidth
|
||||
|
||||
def compiler_ctor(self):
|
||||
if self._llvm_bitwidth is None:
|
||||
return 'i({})'.format(self.bitwidth())
|
||||
else:
|
||||
return 'i_({}, {})'.format(self.bitwidth(),
|
||||
self._llvm_bitwidth)
|
||||
|
||||
def llvm_name(self):
|
||||
bw = self._llvm_bitwidth or self.bitwidth()
|
||||
return 'i{}'.format(bw)
|
||||
|
||||
def rust_name(self):
|
||||
return 'i{}'.format(self.bitwidth())
|
||||
|
||||
class Unsigned(Number):
|
||||
def __init__(self, bitwidth, llvm_bitwidth = None):
|
||||
Number.__init__(self, bitwidth)
|
||||
self._llvm_bitwidth = llvm_bitwidth
|
||||
|
||||
def compiler_ctor(self):
|
||||
if self._llvm_bitwidth is None:
|
||||
return 'u({})'.format(self.bitwidth())
|
||||
else:
|
||||
return 'u_({}, {})'.format(self.bitwidth(),
|
||||
self._llvm_bitwidth)
|
||||
|
||||
def llvm_name(self):
|
||||
bw = self._llvm_bitwidth or self.bitwidth()
|
||||
return 'i{}'.format(bw)
|
||||
|
||||
def rust_name(self):
|
||||
return 'u{}'.format(self.bitwidth())
|
||||
|
||||
class Float(Number):
|
||||
def __init__(self, bitwidth):
|
||||
assert bitwidth in (32, 64)
|
||||
Number.__init__(self, bitwidth)
|
||||
|
||||
def compiler_ctor(self):
|
||||
return 'f({})'.format(self.bitwidth())
|
||||
|
||||
def llvm_name(self):
|
||||
return 'f{}'.format(self.bitwidth())
|
||||
|
||||
def rust_name(self):
|
||||
return 'f{}'.format(self.bitwidth())
|
||||
|
||||
class Vector(Type):
|
||||
def __init__(self, elem, length):
|
||||
assert isinstance(elem, Type) and not isinstance(elem, Vector)
|
||||
Type.__init__(self,
|
||||
elem.bitwidth() * length)
|
||||
self._length = length
|
||||
self._elem = elem
|
||||
|
||||
def modify(self, spec, width):
|
||||
if spec == 'h':
|
||||
return Vector(self._elem, self._length // 2)
|
||||
elif spec == 'd':
|
||||
return Vector(self._elem, self._length * 2)
|
||||
elif spec.startswith('x'):
|
||||
new_bitwidth = int(spec[1:])
|
||||
return Vector(self._elem, new_bitwidth // self._elem.bitwidth())
|
||||
else:
|
||||
return Vector(self._elem.modify(spec, width), self._length)
|
||||
|
||||
def compiler_ctor(self):
|
||||
return 'v({}, {})'.format(self._elem.compiler_ctor(), self._length)
|
||||
|
||||
def rust_name(self):
|
||||
return '{}x{}'.format(self._elem.rust_name(), self._length)
|
||||
|
||||
def type_info(self, platform_info):
|
||||
elem_info = self._elem.type_info(platform_info)
|
||||
return elem_info.vectorize(self._length,
|
||||
platform_info.width_info(self.bitwidth()))
|
||||
|
||||
class Aggregate(Type):
|
||||
def __init__(self, flatten, elems):
|
||||
self._flatten = flatten
|
||||
self._elems = elems
|
||||
Type.__init__(self, sum(elem.bitwidth() for elem in elems))
|
||||
|
||||
def __repr__(self):
|
||||
return '<Aggregate {}>'.format(self._elems)
|
||||
|
||||
def compiler_ctor(self):
|
||||
return 'agg({}, vec![{}])'.format('true' if self._flatten else 'false',
|
||||
', '.join(elem.compiler_ctor() for elem in self._elems))
|
||||
|
||||
def rust_name(self):
|
||||
return '({})'.format(', '.join(elem.rust_name() for elem in self._elems))
|
||||
|
||||
def type_info(self, platform_info):
|
||||
#return PlatformTypeInfo(None, None, self._llvm_name)
|
||||
return None
|
||||
|
||||
|
||||
TYPE_ID_LOOKUP = {'i': [Signed, Unsigned],
|
||||
's': [Signed],
|
||||
'u': [Unsigned],
|
||||
'f': [Float]}
|
||||
|
||||
class TypeSpec(object):
|
||||
def __init__(self, spec):
|
||||
if not isinstance(spec, list):
|
||||
spec = [spec]
|
||||
|
||||
self.spec = spec
|
||||
|
||||
def enumerate(self, width):
|
||||
for spec in self.spec:
|
||||
match = SPEC.match(spec)
|
||||
if match:
|
||||
id = match.group('id')
|
||||
is_vector = id.islower()
|
||||
type_ctors = TYPE_ID_LOOKUP[id.lower()]
|
||||
|
||||
start = match.group('start')
|
||||
if start is not None:
|
||||
end = match.group('end')
|
||||
llvm_width = None
|
||||
else:
|
||||
start = end = match.group('width')
|
||||
llvm_width = match.group('llvm_width')
|
||||
start = int(start)
|
||||
end = int(end)
|
||||
|
||||
bitwidth = start
|
||||
while bitwidth <= end:
|
||||
for ctor in type_ctors:
|
||||
if llvm_width is not None:
|
||||
assert not is_vector
|
||||
llvm_width = int(llvm_width)
|
||||
assert llvm_width < bitwidth
|
||||
scalar = ctor(bitwidth, llvm_width)
|
||||
else:
|
||||
scalar = ctor(bitwidth)
|
||||
|
||||
if is_vector:
|
||||
yield Vector(scalar, width // bitwidth)
|
||||
else:
|
||||
yield scalar
|
||||
bitwidth *= 2
|
||||
else:
|
||||
print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
|
||||
|
||||
def resolve(self, width, zero):
|
||||
assert len(self.spec) == 1
|
||||
spec = self.spec[0]
|
||||
match = SPEC.match(spec)
|
||||
if match:
|
||||
id = match.group('id')
|
||||
if id is not None:
|
||||
options = list(self.enumerate(width))
|
||||
assert len(options) == 1
|
||||
return options[0]
|
||||
reference = match.group('reference')
|
||||
if reference != '0':
|
||||
raise NotImplementedError('only argument 0 (return value) references are supported')
|
||||
ret = zero
|
||||
for x in match.group('modifiers') or []:
|
||||
ret = ret.modify(x, width)
|
||||
force = match.group('force_width')
|
||||
if force is not None:
|
||||
ret = ret.modify(force, width)
|
||||
return ret
|
||||
elif spec.startswith('('):
|
||||
if spec.endswith(')'):
|
||||
raise NotImplementedError()
|
||||
elif spec.endswith(')f'):
|
||||
true_spec = spec[1:-2]
|
||||
flatten = True
|
||||
elems = [TypeSpec(subspec).resolve(width, zero) for subspec in true_spec.split(',')]
|
||||
return Aggregate(flatten, elems)
|
||||
|
||||
class GenericIntrinsic(object):
|
||||
def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
|
||||
self._platform = platform
|
||||
self.intrinsic = intrinsic
|
||||
self.widths = map(int, widths)
|
||||
self.llvm_name = llvm_name
|
||||
self.ret = TypeSpec(ret)
|
||||
self.args = list(map(TypeSpec, args))
|
||||
|
||||
def monomorphise(self):
|
||||
for width in self.widths:
|
||||
# must be a power of two
|
||||
assert width & (width - 1) == 0
|
||||
for ret in self.ret.enumerate(width):
|
||||
args = [arg.resolve(width, ret) for arg in self.args]
|
||||
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, self.llvm_name,
|
||||
ret, args)
|
||||
|
||||
class MonomorphicIntrinsic(object):
|
||||
def __init__(self, platform, intrinsic, width, llvm_name, ret, args):
|
||||
self._platform = platform
|
||||
self._intrinsic = intrinsic
|
||||
self._width = '' if width == 64 else 'q'
|
||||
self._llvm_name = llvm_name
|
||||
self._ret_raw = ret
|
||||
self._ret = ret.type_info(platform)
|
||||
self._args_raw = args
|
||||
self._args = [arg.type_info(platform) for arg in args]
|
||||
|
||||
def llvm_name(self):
|
||||
if self._llvm_name.startswith('!'):
|
||||
return self._llvm_name[1:].format(self._ret, *self._args)
|
||||
else:
|
||||
return self._platform.llvm_prefix() + self._llvm_name.format(self._ret, *self._args)
|
||||
|
||||
def intrinsic_suffix(self):
|
||||
return self._intrinsic.format(self._ret,
|
||||
*self._args,
|
||||
width = self._width)
|
||||
|
||||
def intrinsic_name(self):
|
||||
return self._platform.platform().intrinsic_prefix() + self.intrinsic_suffix()
|
||||
|
||||
def compiler_args(self):
|
||||
return ', '.join(arg.compiler_ctor() for arg in self._args_raw)
|
||||
|
||||
def compiler_ret(self):
|
||||
return self._ret_raw.compiler_ctor()
|
||||
|
||||
def compiler_signature(self):
|
||||
return '({}) -> {}'.format(self.compiler_args(), self.compiler_ret())
|
||||
|
||||
def intrinsic_signature(self):
|
||||
names = 'xyzwabcdef'
|
||||
return '({}) -> {}'.format(', '.join('{}: {}'.format(name, arg.rust_name())
|
||||
for name, arg in zip(names, self._args_raw)),
|
||||
self._ret_raw.rust_name())
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
description = 'Render an intrinsic definition JSON to various formats.',
|
||||
epilog = textwrap.dedent('''\
|
||||
An intrinsic definition consists of a map with fields:
|
||||
- intrinsic: pattern for the name(s) of the vendor's C intrinsic(s)
|
||||
- llvm: pattern for the name(s) of the internal llvm intrinsic(s)
|
||||
- width: a vector of vector bit-widths the pattern works with
|
||||
- ret: type specifier for the return value
|
||||
- arguments: vector of type specifiers for arguments
|
||||
|
||||
The width and types describe a range of possible intrinsics,
|
||||
and these are fed back into the intrinsic and llvm patterns to
|
||||
create the appropriate definitions.
|
||||
|
||||
## Type specifier grammar
|
||||
|
||||
```
|
||||
type := vector | scalar | aggregate | reference
|
||||
|
||||
vector := vector_elem width |
|
||||
vector_elem := 'i' | 'u' | 's' | 'f'
|
||||
|
||||
scalar := scalar_type number llvm_width?
|
||||
scalar_type := 'U' | 'S' | 'F'
|
||||
llvm_width := '/' number
|
||||
|
||||
aggregate := '(' (type),* ')' 'f'?
|
||||
|
||||
reference := number modifiers*
|
||||
modifiers := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
|
||||
'x' number
|
||||
|
||||
|
||||
width = number | '(' number '-' number ')'
|
||||
|
||||
number = [0-9]+
|
||||
```
|
||||
|
||||
## Vectors
|
||||
|
||||
The vector grammar is a pattern describing many possibilities
|
||||
for arguments/return value. The `vector_elem` describes the
|
||||
types of elements to use, and the `width` describes the (range
|
||||
of) widths for those elements, which are then placed into a
|
||||
vector with the `width` bitwidth. E.g. if an intrinsic has a
|
||||
`width` that includes 128, and the return value is `i(8-32)`,
|
||||
then some instantiation of that intrinsic will be `u8x16`,
|
||||
`u32x4`, `i32x4`, etc.
|
||||
|
||||
### Elements
|
||||
|
||||
- i: integer, both signed and unsigned
|
||||
- u: unsigned integer
|
||||
- s: signed integer
|
||||
- f: float
|
||||
|
||||
## Scalars
|
||||
|
||||
Similar to vectors, but these describe a single concrete type,
|
||||
not a range. The number is the bitwidth. The optional
|
||||
`llvm_width` is the bitwidth of the integer that should be
|
||||
passed to LLVM (by truncating the Rust argument): this only
|
||||
works with scalar integers and the LLVM width must be smaller
|
||||
than the Rust width.
|
||||
|
||||
### Types
|
||||
|
||||
- U: unsigned integer
|
||||
- S: signed integer
|
||||
- F: float
|
||||
|
||||
## Aggregates
|
||||
|
||||
An aggregate is a collection of multiple types; a tuple in
|
||||
Rust terms, or an unnamed struct in LLVM. The `f` modifiers
|
||||
forces the tuple to be flattened in the LLVM
|
||||
intrinsic. E.g. if `llvm.foo` takes `(F32,S32)`:
|
||||
|
||||
- no `f` corresponds to `declare ... @llvm.foo({float, i32})`.
|
||||
- having an `f` corresponds to `declare ... @llvm.foo(float, i32)`.
|
||||
|
||||
|
||||
(Currently aggregates can not contain other aggregates.)
|
||||
|
||||
## References
|
||||
|
||||
A reference uses the type of another argument, with possible
|
||||
modifications. The number refers to the type to use, starting
|
||||
with 0 == return value, 1 == first argument, 2 == second
|
||||
argument, etc. (Currently only referencing 0, the return
|
||||
value, is supported.)
|
||||
|
||||
### Modifiers
|
||||
|
||||
- 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
|
||||
- 'h': half the length of the vector (u32x4 -> u32x2)
|
||||
- 'd': double the length of the vector (u32x2 -> u32x4)
|
||||
- 'n': narrow the element of the vector (u32x4 -> u16x4)
|
||||
- 'w': widen the element of the vector (u16x4 -> u32x4)
|
||||
- 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4)
|
||||
- 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4)
|
||||
- 'x' number: force the type to be a vector of bitwidth `number`.
|
||||
'''))
|
||||
parser.add_argument('--format', choices=FORMATS, required=True,
|
||||
help = 'Output format.')
|
||||
parser.add_argument('-o', '--out', type=argparse.FileType('w'), default=sys.stdout,
|
||||
help = 'File to output to (default stdout).')
|
||||
parser.add_argument('-i', '--info', type=argparse.FileType('r'),
|
||||
help = 'File containing platform specific information to merge into'
|
||||
'the input files\' header.')
|
||||
parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'), nargs='+',
|
||||
help = 'JSON files to load')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
class ExternBlock(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def open(self, platform):
|
||||
return 'extern "platform-intrinsic" {'
|
||||
|
||||
def render(self, mono):
|
||||
return ' fn {}{};'.format(mono.intrinsic_name(),
|
||||
mono.intrinsic_signature())
|
||||
|
||||
def close(self):
|
||||
return '}'
|
||||
|
||||
class CompilerDefs(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def open(self, platform):
|
||||
return '''\
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use {{Intrinsic, i, i_, u, u_, f, v, agg}};
|
||||
use IntrinsicDef::Named;
|
||||
use rustc::middle::ty;
|
||||
|
||||
pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {{
|
||||
if !name.starts_with("{0}") {{ return None }}
|
||||
Some(match &name["{0}".len()..] {{'''.format(platform.intrinsic_prefix())
|
||||
|
||||
def render(self, mono):
|
||||
return '''\
|
||||
"{}" => Intrinsic {{
|
||||
inputs: vec![{}],
|
||||
output: {},
|
||||
definition: Named("{}")
|
||||
}},'''.format(mono.intrinsic_suffix(),
|
||||
mono.compiler_args(),
|
||||
mono.compiler_ret(),
|
||||
mono.llvm_name())
|
||||
|
||||
def close(self):
|
||||
return '''\
|
||||
_ => return None,
|
||||
})
|
||||
}'''
|
||||
|
||||
FORMATS = {
|
||||
'extern-block': ExternBlock(),
|
||||
'compiler-defs': CompilerDefs(),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
ins = args.in_
|
||||
out = args.out
|
||||
out_format = FORMATS[args.format]
|
||||
info = args.info
|
||||
one_file_no_info = False
|
||||
if len(ins) > 1 and info is None:
|
||||
print('error: cannot have multiple inputs without an info header.', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
elif info is None:
|
||||
info = ins[0]
|
||||
one_file_no_info = True
|
||||
info_json = json.load(info)
|
||||
platform = PlatformInfo(info_json)
|
||||
|
||||
print(out_format.open(platform), file=out)
|
||||
|
||||
for in_ in ins:
|
||||
|
||||
if one_file_no_info:
|
||||
data = info_json
|
||||
else:
|
||||
data = json.load(in_)
|
||||
data.update(info_json)
|
||||
|
||||
intrinsics = IntrinsicSet(platform, data)
|
||||
for intr in intrinsics.intrinsics():
|
||||
for mono in intr.monomorphise():
|
||||
print(out_format.render(mono), file=out)
|
||||
|
||||
print(out_format.close(), file=out)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
152
src/etc/platform-intrinsics/x86/avx.json
Normal file
152
src/etc/platform-intrinsics/x86/avx.json
Normal file
@ -0,0 +1,152 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.avx.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "256_addsub_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "addsub.{0.data_type}.256",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_dp_ps",
|
||||
"width": [256],
|
||||
"llvm": "dp.ps.256",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hadd_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "hadd.{0.data_type}.256",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hsub_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "hsub.{0.data_type}.256",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_max_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "max.{0.data_type}.256",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_min_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "min.{0.data_type}.256",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_movemask_ps",
|
||||
"width": [256],
|
||||
"llvm": "movmsk.ps.256",
|
||||
"ret": "S32",
|
||||
"args": ["f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_movemask_pd",
|
||||
"width": [256],
|
||||
"llvm": "movmsk.pd.256",
|
||||
"ret": "S32",
|
||||
"args": ["f64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{0.width_mm}_permutevar_{0.data_type}",
|
||||
"width": [128, 256],
|
||||
"llvm": "vpermilvar.{0.data_type}{0.width_suffix}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_rcp_ps",
|
||||
"width": [256],
|
||||
"llvm": "rcp.ps.256",
|
||||
"ret": "f32",
|
||||
"args": ["f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_rsqrt_ps",
|
||||
"width": [256],
|
||||
"llvm": "rsqrt.ps.256",
|
||||
"ret": "f32",
|
||||
"args": ["f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_sqrt_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "!llvm.sqrt.{0.llvm_name}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testc_ps",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestc.ps{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f32", "f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testc_pd",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestc.pd{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f64", "f64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_testc_si256",
|
||||
"width": [256],
|
||||
"llvm": "ptestc.256",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testnzc_ps",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestnzc.ps{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f32", "f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testnzc_pd",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestnzc.pd{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f64", "f64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_testnzc_si256",
|
||||
"width": [256],
|
||||
"llvm": "ptestnzc.256",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testz_ps",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestz.ps{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f32", "f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "{1.width_mm}_testz_pd",
|
||||
"width": [128, 256],
|
||||
"llvm": "vtestz.pd{1.width_suffix}",
|
||||
"ret": "S32",
|
||||
"args": ["f64", "f64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_testz_si256",
|
||||
"width": [256],
|
||||
"llvm": "ptestz.256",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
}
|
||||
]
|
||||
}
|
159
src/etc/platform-intrinsics/x86/avx2.json
Normal file
159
src/etc/platform-intrinsics/x86/avx2.json
Normal file
@ -0,0 +1,159 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.avx2.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "256_abs_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "avx2.pabs.{0.data_type_short}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_adds_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "avx2.padd{0.kind_short}s.{0.data_type_short}",
|
||||
"ret": "i(8-16)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_avg_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "avx2.pavg.{0.data_type_short}",
|
||||
"ret": "u(8-16)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hadd_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "phadd.{0.data_type_short}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hadds_epi16",
|
||||
"width": [256],
|
||||
"llvm": "phadd.sw",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hsub_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "phsub.{0.data_type_short}",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_hsubs_epi16",
|
||||
"width": [256],
|
||||
"llvm": "phsub.sw",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_madd_epi16",
|
||||
"width": [256],
|
||||
"llvm": "pmadd.wd",
|
||||
"ret": "s32",
|
||||
"args": ["s16", "s16"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_maddubs_epi16",
|
||||
"width": [256],
|
||||
"llvm": "pmadd.ub.sw",
|
||||
"ret": "s16",
|
||||
"args": ["s8", "s8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_max_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "pmax{0.kind}.{0.data_type_short}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_min_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "pmin{0.kind}.{0.data_type_short}",
|
||||
"ret": "i(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_movemask_epi8",
|
||||
"width": [256],
|
||||
"llvm": "pmovmskb",
|
||||
"ret": "S32",
|
||||
"args": ["s8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_mpsadbw_epu8",
|
||||
"width": [256],
|
||||
"llvm": "mpsadbw",
|
||||
"ret": "u16",
|
||||
"args": ["u8", "u8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_mul_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "pmul{0.data_type_short}.dq",
|
||||
"ret": "i64",
|
||||
"args": ["0dn", "0dn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_mulhi_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "pmulh{0.data_type_short}.w",
|
||||
"ret": "i16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_mulhrs_epi16",
|
||||
"width": [256],
|
||||
"llvm": "pmul.hr.sw",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_pack{0.kind_short}s_{1.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "pack{0.kind}s{1.data_type_short}{0.data_type_short}",
|
||||
"ret": "i(8-16)",
|
||||
"args": ["0hws", "0hws"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_permutevar8x32_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "perm{0.data_type_short}",
|
||||
"ret": ["s32", "f32"],
|
||||
"args": ["0", "0s"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_sad_epu8",
|
||||
"width": [256],
|
||||
"llvm": "psad.bw",
|
||||
"ret": "u8",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_shuffle_epi8",
|
||||
"width": [256],
|
||||
"llvm": "pshuf.b",
|
||||
"ret": "s8",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_sign_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "psign.{0.data_type_short}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "256_subs_{0.data_type}",
|
||||
"width": [256],
|
||||
"llvm": "psub{0.kind_short}s.{0.data_type_short}",
|
||||
"ret": "i(8-16)",
|
||||
"args": ["0", "0"]
|
||||
}
|
||||
]
|
||||
}
|
28
src/etc/platform-intrinsics/x86/info.json
Normal file
28
src/etc/platform-intrinsics/x86/info.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"platform": "x86",
|
||||
"intrinsic_prefix": "x86_mm",
|
||||
"number_info": {
|
||||
"signed": {
|
||||
"kind": "s",
|
||||
"kind_short": "",
|
||||
"data_type": { "pattern": "epi{bitwidth}" },
|
||||
"data_type_short": { "8": "b", "16": "w", "32": "d", "64": "q" }
|
||||
},
|
||||
"unsigned": {
|
||||
"kind": "u",
|
||||
"kind_short": "u",
|
||||
"data_type": { "pattern": "epu{bitwidth}" },
|
||||
"data_type_short": { "8": "b", "16": "w", "32": "d", "64": "q" }
|
||||
},
|
||||
"float": {
|
||||
"kind": "f",
|
||||
"data_type": { "32": "ps", "64": "pd" },
|
||||
"data_type_short": { "32": "ps", "64": "pd" }
|
||||
}
|
||||
},
|
||||
"width_info": {
|
||||
"128": { "width_mm": "", "width_suffix": "" },
|
||||
"256": { "width_mm": "256", "width_suffix": ".256" },
|
||||
"512": { "width_mm": "512", "width_suffix": ".512" }
|
||||
}
|
||||
}
|
47
src/etc/platform-intrinsics/x86/sse.json
Normal file
47
src/etc/platform-intrinsics/x86/sse.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.sse.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_movemask_ps",
|
||||
"width": [128],
|
||||
"llvm": "movmsk.ps",
|
||||
"ret": "S32",
|
||||
"args": ["f32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_max_ps",
|
||||
"width": [128],
|
||||
"llvm": "max.ps",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_min_ps",
|
||||
"width": [128],
|
||||
"llvm": "min.ps",
|
||||
"ret": "f32",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_rsqrt_ps",
|
||||
"width": [128],
|
||||
"llvm": "rsqrt.ps",
|
||||
"ret": "f32",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_rcp_ps",
|
||||
"width": [128],
|
||||
"llvm": "rcp.ps",
|
||||
"ret": "f32",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_sqrt_ps",
|
||||
"width": [128],
|
||||
"llvm": "!llvm.sqrt.v4f32",
|
||||
"ret": "f32",
|
||||
"args": ["0"]
|
||||
}
|
||||
]
|
||||
}
|
117
src/etc/platform-intrinsics/x86/sse2.json
Normal file
117
src/etc/platform-intrinsics/x86/sse2.json
Normal file
@ -0,0 +1,117 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.sse2.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_adds_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "padd{0.kind_short}s.{0.data_type_short}",
|
||||
"ret": "i(8-16)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_avg_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pavg.{0.data_type_short}",
|
||||
"ret": "u(8-16)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_madd_epi16",
|
||||
"width": [128],
|
||||
"llvm": "pmadd.wd",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_max_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pmax{0.kind}.{0.data_type_short}",
|
||||
"ret": ["s16", "u8"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_max_pd",
|
||||
"width": [128],
|
||||
"llvm": "max.pd",
|
||||
"ret": "f64",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_min_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pmin{0.kind}.{0.data_type_short}",
|
||||
"ret": ["s16", "u8"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_min_pd",
|
||||
"width": [128],
|
||||
"llvm": "min.pd",
|
||||
"ret": "f64",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_movemask_pd",
|
||||
"width": [128],
|
||||
"llvm": "movmsk.pd",
|
||||
"ret": "S32",
|
||||
"args": ["f64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_movemask_epi8",
|
||||
"width": [128],
|
||||
"llvm": "pmovmskb.128",
|
||||
"ret": "S32",
|
||||
"args": ["s8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_mul_epu32",
|
||||
"width": [128],
|
||||
"llvm": "pmulu.dq",
|
||||
"ret": "s64",
|
||||
"args": ["0dn", "0dn"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_mulhi_ep{0.kind}16",
|
||||
"width": [128],
|
||||
"llvm": "pmulh{0.kind_short}.w",
|
||||
"ret": "i16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_packs_{1.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "packss{1.data_type_short}{0.data_type_short}.128",
|
||||
"ret": "s(8-16)",
|
||||
"args": ["0hw", "0hw"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_packus_epi16",
|
||||
"width": [128],
|
||||
"llvm": "packuswb.128",
|
||||
"ret": "u8",
|
||||
"args": ["s16", "s16"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_sad_epu8",
|
||||
"width": [128],
|
||||
"llvm": "psad.bw",
|
||||
"ret": "u64",
|
||||
"args": ["u8", "u8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_sqrt_pd",
|
||||
"width": [128],
|
||||
"llvm": "!llvm.sqrt.v2f64",
|
||||
"ret": "f64",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_subs_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "psub{0.kind_short}s.{0.data_type_short}",
|
||||
"ret": "i(8-16)",
|
||||
"args": ["0", "0"]
|
||||
}
|
||||
]
|
||||
}
|
26
src/etc/platform-intrinsics/x86/sse3.json
Normal file
26
src/etc/platform-intrinsics/x86/sse3.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.sse3.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_addsub_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "addsub.{0.data_type}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hadd_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "hadd.{0.data_type}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hsub_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "hsub.{0.data_type}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0"]
|
||||
}
|
||||
]
|
||||
}
|
75
src/etc/platform-intrinsics/x86/sse41.json
Normal file
75
src/etc/platform-intrinsics/x86/sse41.json
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.sse41.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_dp_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "dp{0.data_type}",
|
||||
"ret": "f(32-64)",
|
||||
"args": ["0", "0", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_max_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pmax{0.kind}{0.data_type_short}",
|
||||
"ret": ["s8", "u16", "i32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_min_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pmin{0.kind}{0.data_type_short}",
|
||||
"ret": ["s8", "u16", "i32"],
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_minpos_epu16",
|
||||
"width": [128],
|
||||
"llvm": "phminposuw",
|
||||
"ret": "u16",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_mpsadbw_epu8",
|
||||
"width": [128],
|
||||
"llvm": "mpsadbw",
|
||||
"ret": "u16",
|
||||
"args": ["u8", "u8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_mul_epi32",
|
||||
"width": [128],
|
||||
"llvm": "muldq",
|
||||
"ret": "s64",
|
||||
"args": ["s32", "s32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_packus_epi32",
|
||||
"width": [128],
|
||||
"llvm": "packusdw",
|
||||
"ret": "u16",
|
||||
"args": ["s32", "s32"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_testc_si128",
|
||||
"width": [128],
|
||||
"llvm": "ptestc",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_testncz_si128",
|
||||
"width": [128],
|
||||
"llvm": "ptest.nzc",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_testz_si128",
|
||||
"width": [128],
|
||||
"llvm": "ptestz",
|
||||
"ret": "S32",
|
||||
"args": ["u64", "u64"]
|
||||
}
|
||||
]
|
||||
}
|
103
src/etc/platform-intrinsics/x86/sse42.json
Normal file
103
src/etc/platform-intrinsics/x86/sse42.json
Normal file
@ -0,0 +1,103 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.sse42.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_cmpestra",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestria128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestrc",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestric128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestri",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestri128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestrm",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestrm128",
|
||||
"ret": "s8",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestro",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestrio128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestrs",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestris128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpestrz",
|
||||
"width": [128],
|
||||
"llvm": "pcmpestriz128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "S32", "s8", "S32", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistra",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistria128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistrc",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistric128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistri",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistri128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistrm",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistrm128",
|
||||
"ret": "s8",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistro",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistrio128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistrs",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistris128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_cmpistrz",
|
||||
"width": [128],
|
||||
"llvm": "pcmpistriz128",
|
||||
"ret": "S32",
|
||||
"args": ["s8", "s8", "S32/8"]
|
||||
}
|
||||
]
|
||||
}
|
68
src/etc/platform-intrinsics/x86/ssse3.json
Normal file
68
src/etc/platform-intrinsics/x86/ssse3.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"llvm_prefix": "llvm.x86.ssse3.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "_abs_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "pabs.{0.data_type_short}",
|
||||
"ret": "s(8-32)",
|
||||
"args": ["0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hadd_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "phadd.{0.data_type_short}.128",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hadds_epi16",
|
||||
"width": [128],
|
||||
"llvm": "phadd.sw.128",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hsub_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "phsub.{0.data_type_short}.128",
|
||||
"ret": "s(16-32)",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_hsubs_epi16",
|
||||
"width": [128],
|
||||
"llvm": "phsub.sw.128",
|
||||
"ret": "s16",
|
||||
"args": ["0", "0"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_maddubs_epi16",
|
||||
"width": [128],
|
||||
"llvm": "pmadd.ub.sw.128",
|
||||
"ret": "s16",
|
||||
"args": ["s8", "s8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_mulhrs_epi16",
|
||||
"width": [128],
|
||||
"llvm": "pmul.hr.sw.128",
|
||||
"ret": "s16",
|
||||
"args": ["s16", "s16"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_shuffle_epi8",
|
||||
"width": [128],
|
||||
"llvm": "pshuf.b.128",
|
||||
"ret": "s8",
|
||||
"args": ["s8", "s8"]
|
||||
},
|
||||
{
|
||||
"intrinsic": "_sign_{0.data_type}",
|
||||
"width": [128],
|
||||
"llvm": "psign.{0.data_type_short}.128",
|
||||
"ret": "s(8-16)",
|
||||
"args": ["0", "0"]
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -30,58 +30,26 @@ pub struct Intrinsic {
|
||||
|
||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||
pub enum Type {
|
||||
Integer(u8),
|
||||
Integer(/* signed */ bool, u8, /* llvm width */ u8),
|
||||
Float(u8),
|
||||
Pointer(Box<Type>),
|
||||
Vector(Box<Type>, u8),
|
||||
Aggregate(bool, Vec<Type>),
|
||||
}
|
||||
|
||||
pub enum IntrinsicDef {
|
||||
Named(&'static str),
|
||||
}
|
||||
|
||||
fn i(width: u8) -> Type { Type::Integer(width) }
|
||||
fn i(width: u8) -> Type { Type::Integer(true, width, width) }
|
||||
fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) }
|
||||
fn u(width: u8) -> Type { Type::Integer(false, width, width) }
|
||||
#[allow(dead_code)]
|
||||
fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) }
|
||||
fn f(width: u8) -> Type { Type::Float(width) }
|
||||
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
|
||||
|
||||
macro_rules! ty {
|
||||
(f32x8) => (v(f(32), 8));
|
||||
(f64x4) => (v(f(64), 4));
|
||||
|
||||
(i8x32) => (v(i(8), 32));
|
||||
(i16x16) => (v(i(16), 16));
|
||||
(i32x8) => (v(i(32), 8));
|
||||
(i64x4) => (v(i(64), 4));
|
||||
|
||||
(f32x4) => (v(f(32), 4));
|
||||
(f64x2) => (v(f(64), 2));
|
||||
|
||||
(i8x16) => (v(i(8), 16));
|
||||
(i16x8) => (v(i(16), 8));
|
||||
(i32x4) => (v(i(32), 4));
|
||||
(i64x2) => (v(i(64), 2));
|
||||
|
||||
(f32x2) => (v(f(32), 2));
|
||||
(i8x8) => (v(i(8), 8));
|
||||
(i16x4) => (v(i(16), 4));
|
||||
(i32x2) => (v(i(32), 2));
|
||||
(i64x1)=> (v(i(64), 1));
|
||||
|
||||
(i64) => (i(64));
|
||||
(i32) => (i(32));
|
||||
(i16) => (i(16));
|
||||
(i8) => (i(8));
|
||||
(f32) => (f(32));
|
||||
(f64) => (f(64));
|
||||
}
|
||||
macro_rules! plain {
|
||||
($name: expr, ($($inputs: tt),*) -> $output: tt) => {
|
||||
Intrinsic {
|
||||
inputs: vec![$(ty!($inputs)),*],
|
||||
output: ty!($output),
|
||||
definition: ::IntrinsicDef::Named($name)
|
||||
}
|
||||
}
|
||||
fn agg(flatten: bool, types: Vec<Type>) -> Type {
|
||||
Type::Aggregate(flatten, types)
|
||||
}
|
||||
|
||||
mod x86;
|
||||
@ -91,11 +59,11 @@ mod aarch64;
|
||||
impl Intrinsic {
|
||||
pub fn find<'tcx>(tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
|
||||
if name.starts_with("x86_") {
|
||||
x86::find(tcx, &name["x86_".len()..])
|
||||
x86::find(tcx, name)
|
||||
} else if name.starts_with("arm_") {
|
||||
arm::find(tcx, &name["arm_".len()..])
|
||||
arm::find(tcx, name)
|
||||
} else if name.starts_with("aarch64_") {
|
||||
aarch64::find(tcx, &name["aarch64_".len()..])
|
||||
aarch64::find(tcx, name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -171,9 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
|
||||
let _icx = push_ctxt("trans_intrinsic_call");
|
||||
|
||||
let ret_ty = match callee_ty.sty {
|
||||
let (arg_tys, ret_ty) = match callee_ty.sty {
|
||||
ty::TyBareFn(_, ref f) => {
|
||||
bcx.tcx().erase_late_bound_regions(&f.sig.output())
|
||||
(bcx.tcx().erase_late_bound_regions(&f.sig.inputs()),
|
||||
bcx.tcx().erase_late_bound_regions(&f.sig.output()))
|
||||
}
|
||||
_ => panic!("expected bare_fn in trans_intrinsic_call")
|
||||
};
|
||||
@ -926,25 +927,105 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
Some(intr) => intr,
|
||||
None => ccx.sess().span_bug(foreign_item.span, "unknown intrinsic"),
|
||||
};
|
||||
fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type) -> Type {
|
||||
fn one<T>(x: Vec<T>) -> T {
|
||||
assert_eq!(x.len(), 1);
|
||||
x.into_iter().next().unwrap()
|
||||
}
|
||||
fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type,
|
||||
any_changes_needed: &mut bool) -> Vec<Type> {
|
||||
use intrinsics::Type::*;
|
||||
match *t {
|
||||
Integer(x) => Type::ix(ccx, x as u64),
|
||||
Integer(_signed, width, llvm_width) => {
|
||||
*any_changes_needed |= width != llvm_width;
|
||||
vec![Type::ix(ccx, llvm_width as u64)]
|
||||
}
|
||||
Float(x) => {
|
||||
match x {
|
||||
32 => Type::f32(ccx),
|
||||
64 => Type::f64(ccx),
|
||||
32 => vec![Type::f32(ccx)],
|
||||
64 => vec![Type::f64(ccx)],
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
Pointer(_) => unimplemented!(),
|
||||
Vector(ref t, length) => Type::vector(&ty_to_type(ccx, t),
|
||||
length as u64)
|
||||
Vector(ref t, length) => {
|
||||
let elem = one(ty_to_type(ccx, t,
|
||||
any_changes_needed));
|
||||
vec![Type::vector(&elem,
|
||||
length as u64)]
|
||||
}
|
||||
Aggregate(false, _) => unimplemented!(),
|
||||
Aggregate(true, ref contents) => {
|
||||
*any_changes_needed = true;
|
||||
contents.iter()
|
||||
.flat_map(|t| ty_to_type(ccx, t, any_changes_needed))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let inputs = intr.inputs.iter().map(|t| ty_to_type(ccx, t)).collect::<Vec<_>>();
|
||||
let outputs = ty_to_type(ccx, &intr.output);
|
||||
// This allows an argument list like `foo, (bar, baz),
|
||||
// qux` to be converted into `foo, bar, baz, qux`, and
|
||||
// integer arguments to be truncated as needed.
|
||||
fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
t: &intrinsics::Type,
|
||||
arg_type: Ty<'tcx>,
|
||||
llarg: ValueRef)
|
||||
-> Vec<ValueRef>
|
||||
{
|
||||
match *t {
|
||||
intrinsics::Type::Aggregate(true, ref contents) => {
|
||||
// We found a tuple that needs squishing! So
|
||||
// run over the tuple and load each field.
|
||||
//
|
||||
// This assumes the type is "simple", i.e. no
|
||||
// destructors, and the contents are SIMD
|
||||
// etc.
|
||||
assert!(!bcx.fcx.type_needs_drop(arg_type));
|
||||
|
||||
let repr = adt::represent_type(bcx.ccx(), arg_type);
|
||||
let repr_ptr = &*repr;
|
||||
(0..contents.len())
|
||||
.map(|i| {
|
||||
Load(bcx, adt::trans_field_ptr(bcx, repr_ptr, llarg, 0, i))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
|
||||
// the LLVM intrinsic uses a smaller integer
|
||||
// size than the C intrinsic's signature, so
|
||||
// we have to trim it down here.
|
||||
vec![Trunc(bcx, llarg, Type::ix(bcx.ccx(), llvm_width as u64))]
|
||||
}
|
||||
_ => vec![llarg],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mut any_changes_needed = false;
|
||||
let inputs = intr.inputs.iter()
|
||||
.flat_map(|t| ty_to_type(ccx, t, &mut any_changes_needed))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut out_changes = false;
|
||||
let outputs = one(ty_to_type(ccx, &intr.output, &mut out_changes));
|
||||
// outputting a flattened aggregate is nonsense
|
||||
assert!(!out_changes);
|
||||
|
||||
let llargs = if !any_changes_needed {
|
||||
// no aggregates to flatten, so no change needed
|
||||
llargs
|
||||
} else {
|
||||
// there are some aggregates that need to be flattened
|
||||
// in the LLVM call, so we need to run over the types
|
||||
// again to find them and extract the arguments
|
||||
intr.inputs.iter()
|
||||
.zip(&llargs)
|
||||
.zip(&arg_tys)
|
||||
.flat_map(|((t, llarg), ty)| modify_as_needed(bcx, t, ty, *llarg))
|
||||
.collect()
|
||||
};
|
||||
assert_eq!(inputs.len(), llargs.len());
|
||||
|
||||
match intr.definition {
|
||||
intrinsics::IntrinsicDef::Named(name) => {
|
||||
let f = declare::declare_cfn(ccx,
|
||||
|
@ -463,13 +463,16 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
|
||||
};
|
||||
|
||||
match *expected {
|
||||
Integer(bits) => match (bits, &t.sty) {
|
||||
(8, &ty::TyInt(ast::TyI8)) | (8, &ty::TyUint(ast::TyU8)) |
|
||||
(16, &ty::TyInt(ast::TyI16)) | (16, &ty::TyUint(ast::TyU16)) |
|
||||
(32, &ty::TyInt(ast::TyI32)) | (32, &ty::TyUint(ast::TyU32)) |
|
||||
(64, &ty::TyInt(ast::TyI64)) | (64, &ty::TyUint(ast::TyU64)) => {},
|
||||
// (The width we pass to LLVM doesn't concern the type checker.)
|
||||
Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) {
|
||||
(true, 8, &ty::TyInt(ast::TyI8)) | (false, 8, &ty::TyUint(ast::TyU8)) |
|
||||
(true, 16, &ty::TyInt(ast::TyI16)) | (false, 16, &ty::TyUint(ast::TyU16)) |
|
||||
(true, 32, &ty::TyInt(ast::TyI32)) | (false, 32, &ty::TyUint(ast::TyU32)) |
|
||||
(true, 64, &ty::TyInt(ast::TyI64)) | (false, 64, &ty::TyUint(ast::TyU64)) => {},
|
||||
_ => simple_error(&format!("`{}`", t),
|
||||
&format!("`i{n}` or `u{n}`", n = bits)),
|
||||
&format!("`{}{n}`",
|
||||
if signed {"i"} else {"u"},
|
||||
n = bits)),
|
||||
},
|
||||
Float(bits) => match (bits, &t.sty) {
|
||||
(32, &ty::TyFloat(ast::TyF32)) |
|
||||
@ -512,5 +515,22 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
|
||||
inner_expected,
|
||||
t_ty)
|
||||
}
|
||||
Aggregate(_flatten, ref expected_contents) => {
|
||||
match t.sty {
|
||||
ty::TyTuple(ref contents) => {
|
||||
if contents.len() != expected_contents.len() {
|
||||
simple_error(&format!("tuple with length {}", contents.len()),
|
||||
&format!("tuple with length {}", expected_contents.len()));
|
||||
return
|
||||
}
|
||||
for (e, c) in expected_contents.iter().zip(contents) {
|
||||
match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
|
||||
e, c)
|
||||
}
|
||||
}
|
||||
_ => simple_error(&format!("`{}`", t),
|
||||
&format!("tuple")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,27 +25,38 @@ struct f32x4(f32, f32, f32, f32);
|
||||
#[repr(simd)]
|
||||
struct i64x2(i64, i64);
|
||||
|
||||
// signed vs. unsigned doesn't matter
|
||||
mod i {
|
||||
use i16x8;
|
||||
// correct signatures work well
|
||||
mod right {
|
||||
use {i16x8, u16x8};
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i16x8;
|
||||
fn x86_mm_adds_epu16(x: u16x8, y: u16x8) -> u16x8;
|
||||
}
|
||||
}
|
||||
mod u {
|
||||
use u16x8;
|
||||
// but incorrect ones don't.
|
||||
|
||||
mod signedness {
|
||||
use {i16x8, u16x8};
|
||||
// signedness matters
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
|
||||
//~^ ERROR intrinsic argument 1 has wrong type
|
||||
//~^^ ERROR intrinsic argument 2 has wrong type
|
||||
//~^^^ ERROR intrinsic return value has wrong type
|
||||
fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
|
||||
//~^ ERROR intrinsic argument 1 has wrong type
|
||||
//~^^ ERROR intrinsic argument 2 has wrong type
|
||||
//~^^^ ERROR intrinsic return value has wrong type
|
||||
}
|
||||
}
|
||||
// but lengths do
|
||||
// as do lengths
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2;
|
||||
//~^ ERROR intrinsic argument 1 has wrong type
|
||||
//~^^ ERROR intrinsic argument 2 has wrong type
|
||||
//~^^^ ERROR intrinsic return value has wrong type
|
||||
}
|
||||
// and so does int vs. float
|
||||
// and so does int vs. float:
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_mm_max_ps(x: i32x4, y: i32x4) -> i32x4;
|
||||
//~^ ERROR intrinsic argument 1 has wrong type
|
||||
|
Loading…
Reference in New Issue
Block a user