get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/812164/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 812164,
    "url": "http://patchwork.ozlabs.org/api/patches/812164/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/150506083546.19604.543091497330269756.stgit@frigg.lan/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<150506083546.19604.543091497330269756.stgit@frigg.lan>",
    "list_archive_url": null,
    "date": "2017-09-10T16:27:15",
    "name": "[4/7] tcg: Add support for \"inlining\" regions of code",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "aeba3d6092eb916eb937ce3f605b1ab847eab502",
    "submitter": {
        "id": 9099,
        "url": "http://patchwork.ozlabs.org/api/people/9099/?format=api",
        "name": "Lluís Vilanova",
        "email": "vilanova@ac.upc.edu"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/150506083546.19604.543091497330269756.stgit@frigg.lan/mbox/",
    "series": [
        {
            "id": 2406,
            "url": "http://patchwork.ozlabs.org/api/series/2406/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2406",
            "date": "2017-09-10T16:11:07",
            "name": "trace: Add guest code events",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/2406/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/812164/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/812164/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xqxLG5Sfjz9rxm\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 11 Sep 2017 02:27:50 +1000 (AEST)",
            "from localhost ([::1]:53577 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dr55I-0008Ek-RO\n\tfor incoming@patchwork.ozlabs.org; Sun, 10 Sep 2017 12:27:48 -0400",
            "from eggs.gnu.org ([2001:4830:134:3::10]:42496)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1dr54y-0008EW-AC\n\tfor qemu-devel@nongnu.org; Sun, 10 Sep 2017 12:27:29 -0400",
            "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1dr54u-0005fB-9Z\n\tfor qemu-devel@nongnu.org; Sun, 10 Sep 2017 12:27:28 -0400",
            "from roura.ac.upc.es ([147.83.33.10]:57808)\n\tby eggs.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1dr54t-0005es-N1\n\tfor qemu-devel@nongnu.org; Sun, 10 Sep 2017 12:27:24 -0400",
            "from correu-1.ac.upc.es (correu-1.ac.upc.es [147.83.30.91])\n\tby roura.ac.upc.es (8.13.8/8.13.8) with ESMTP id v8AGRMaJ020492;\n\tSun, 10 Sep 2017 18:27:22 +0200",
            "from localhost (unknown [132.68.137.153])\n\tby correu-1.ac.upc.es (Postfix) with ESMTPSA id B3663201;\n\tSun, 10 Sep 2017 18:27:16 +0200 (CEST)"
        ],
        "From": "=?utf-8?b?TGx1w61z?= Vilanova <vilanova@ac.upc.edu>",
        "To": "qemu-devel@nongnu.org",
        "Date": "Sun, 10 Sep 2017 19:27:15 +0300",
        "Message-Id": "<150506083546.19604.543091497330269756.stgit@frigg.lan>",
        "X-Mailer": "git-send-email 2.14.1",
        "In-Reply-To": "<150505986682.19604.11937392314067517230.stgit@frigg.lan>",
        "References": "<150505986682.19604.11937392314067517230.stgit@frigg.lan>",
        "User-Agent": "StGit/0.18",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "quoted-printable",
        "X-MIME-Autoconverted": "from 8bit to quoted-printable by roura.ac.upc.es id\n\tv8AGRMaJ020492",
        "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.6.x [fuzzy]",
        "X-Received-From": "147.83.33.10",
        "Subject": "[Qemu-devel] [PATCH 4/7] tcg: Add support for \"inlining\" regions of\n\tcode",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.21",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Cc": "Stefan Hajnoczi <stefanha@redhat.com>,\n\tRichard Henderson <rth@twiddle.net>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"
    },
    "content": "TCG BBLs and instructions have multiple exit points from where to raise\ntracing events, but some of the necessary information in the generic\ndisassembly infrastructure is not available until after generating these\nexit points.\n\nThis patch adds support for \"inline points\" (where the tracing code will\nbe placed), and \"inline regions\" (which identify the TCG code that must\nbe inlined). The TCG compiler will basically copy each inline region to\nany inline points that reference it.\n\nSigned-off-by: Lluís Vilanova <vilanova@ac.upc.edu>\n---\n include/qemu/log.h      |    1 \n include/qemu/typedefs.h |    1 \n tcg/tcg-op.h            |   39 +++++++++++\n tcg/tcg-opc.h           |    3 +\n tcg/tcg.c               |  166 +++++++++++++++++++++++++++++++++++++++++++++++\n tcg/tcg.h               |   18 +++++\n util/log.c              |    2 +\n 7 files changed, 230 insertions(+)",
    "diff": "diff --git a/include/qemu/log.h b/include/qemu/log.h\nindex a50e994c21..23acc63c73 100644\n--- a/include/qemu/log.h\n+++ b/include/qemu/log.h\n@@ -43,6 +43,7 @@ static inline bool qemu_log_separate(void)\n #define CPU_LOG_PAGE       (1 << 14)\n #define LOG_TRACE          (1 << 15)\n #define CPU_LOG_TB_OP_IND  (1 << 16)\n+#define CPU_LOG_TB_OP_INLINE (1 << 17)\n \n /* Returns true if a bit is set in the current loglevel mask\n  */\ndiff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h\nindex 39bc8351a3..2fb5670af3 100644\n--- a/include/qemu/typedefs.h\n+++ b/include/qemu/typedefs.h\n@@ -96,6 +96,7 @@ typedef struct SerialState SerialState;\n typedef struct SHPCDevice SHPCDevice;\n typedef struct SMBusDevice SMBusDevice;\n typedef struct SSIBus SSIBus;\n+typedef struct TCGInlineLabel TCGInlineLabel;\n typedef struct uWireSlave uWireSlave;\n typedef struct VirtIODevice VirtIODevice;\n typedef struct Visitor Visitor;\ndiff --git a/tcg/tcg-op.h b/tcg/tcg-op.h\nindex 5d3278f243..da3784f8f2 100644\n--- a/tcg/tcg-op.h\n+++ b/tcg/tcg-op.h\n@@ -326,6 +326,45 @@ void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg);\n void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg);\n void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg);\n \n+static inline int _get_inline_index(TCGInlineLabel *l)\n+{\n+    TCGContext *s = &tcg_ctx;\n+    return l - s->inline_labels;\n+}\n+\n+static inline void gen_set_inline_point(TCGInlineLabel *l)\n+{\n+    TCGContext *s = &tcg_ctx;\n+    TCGInlinePoint *p = tcg_malloc(sizeof(TCGInlinePoint));\n+    p->op_idx = s->gen_next_op_idx;\n+    p->next_point = l->first_point;\n+    l->first_point = p;\n+    tcg_gen_op1i(INDEX_op_set_inline_point,\n+                 _get_inline_index(l));\n+}\n+\n+static inline void gen_set_inline_region_begin(TCGInlineLabel *l)\n+{\n+    TCGContext *s = &tcg_ctx;\n+    if (l->begin_op_idx != -1) {\n+        tcg_abort();\n+    }\n+    l->begin_op_idx = s->gen_next_op_idx;\n+    tcg_gen_op1i(INDEX_op_set_inline_region_begin,\n+                 _get_inline_index(l));\n+}\n+\n+static inline void gen_set_inline_region_end(TCGInlineLabel *l)\n+{\n+    TCGContext *s = &tcg_ctx;\n+    if (l->begin_op_idx == -1) {\n+        tcg_abort();\n+    }\n+    l->end_op_idx = s->gen_next_op_idx;\n+    tcg_gen_op1i(INDEX_op_set_inline_region_end,\n+                 _get_inline_index(l));\n+}\n+\n static inline void tcg_gen_discard_i32(TCGv_i32 arg)\n {\n     tcg_gen_op1_i32(INDEX_op_discard, arg);\ndiff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h\nindex 956fb1e9f3..279ac0dc1f 100644\n--- a/tcg/tcg-opc.h\n+++ b/tcg/tcg-opc.h\n@@ -29,6 +29,9 @@\n /* predefined ops */\n DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)\n DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)\n+DEF(set_inline_point, 0, 0, 1, TCG_OPF_NOT_PRESENT)\n+DEF(set_inline_region_begin, 0, 0, 1, TCG_OPF_NOT_PRESENT)\n+DEF(set_inline_region_end, 0, 0, 1, TCG_OPF_NOT_PRESENT)\n \n /* variable number of parameters */\n DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT)\ndiff --git a/tcg/tcg.c b/tcg/tcg.c\nindex fd8a3dfe93..b48196da27 100644\n--- a/tcg/tcg.c\n+++ b/tcg/tcg.c\n@@ -251,6 +251,23 @@ TCGLabel *gen_new_label(void)\n     return l;\n }\n \n+TCGInlineLabel *gen_new_inline_label(void)\n+{\n+    TCGContext *s = &tcg_ctx;\n+    int idx;\n+    TCGInlineLabel *l;\n+\n+    if (s->nb_inline_labels >= TCG_MAX_INLINE_LABELS) {\n+        tcg_abort();\n+    }\n+    idx = s->nb_inline_labels++;\n+    l = &s->inline_labels[idx];\n+    l->first_point = NULL;\n+    l->begin_op_idx = -1;\n+    l->end_op_idx = -1;\n+    return l;\n+}\n+\n #include \"tcg-target.inc.c\"\n \n /* pool based memory allocation */\n@@ -462,6 +479,10 @@ void tcg_func_start(TCGContext *s)\n     s->nb_labels = 0;\n     s->current_frame_offset = s->frame_start;\n \n+    s->inline_labels = tcg_malloc(sizeof(TCGInlineLabel) *\n+                                  TCG_MAX_INLINE_LABELS);\n+    s->nb_inline_labels = 0;\n+\n #ifdef CONFIG_DEBUG_TCG\n     s->goto_tb_issue_mask = 0;\n #endif\n@@ -1423,6 +1444,139 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *temp_state)\n     }\n }\n \n+static inline int _get_op_next(TCGContext *s, int idx)\n+{\n+    return s->gen_op_buf[idx].next;\n+}\n+\n+static inline void _set_op_next(TCGContext *s, int idx, int next)\n+{\n+    s->gen_op_buf[idx].next = next;\n+}\n+\n+static inline int _get_op_prev(TCGContext *s, int idx)\n+{\n+    return s->gen_op_buf[idx].prev;\n+}\n+\n+static inline void _set_op_prev(TCGContext *s, int idx, int prev)\n+{\n+    s->gen_op_buf[idx].prev = prev;\n+}\n+\n+static inline void _inline_region_ignore(TCGContext *s, TCGInlineLabel *l)\n+{\n+    int l_prev = _get_op_prev(s, l->begin_op_idx);\n+    int l_next = _get_op_next(s, l->end_op_idx);\n+    _set_op_next(s, l_prev, l_next);\n+    _set_op_prev(s, l_next, l_prev);\n+}\n+\n+static inline void _op_ignore(TCGContext *s, int op_idx)\n+{\n+    int p_prev = _get_op_prev(s, op_idx);\n+    int p_next = _get_op_next(s, op_idx);\n+    _set_op_next(s, p_prev, p_next);\n+    _set_op_prev(s, p_next, p_prev);\n+}\n+\n+static inline void _inline_point_ignore(TCGContext *s, TCGInlinePoint *p)\n+{\n+    _op_ignore(s, p->op_idx);\n+}\n+\n+static inline void _inline_weave(TCGContext *s, TCGInlinePoint *p,\n+                                 int begin, int end)\n+{\n+    int begin_prev = _get_op_prev(s, begin);\n+    int end_next = _get_op_next(s, end);\n+    int p_prev = _get_op_prev(s, p->op_idx);\n+    int p_next = _get_op_next(s, p->op_idx);\n+    /* point.prev -> begin */\n+    _set_op_next(s, p_prev, begin);\n+    _set_op_prev(s, begin, p_prev);\n+    /* end -> point.next */\n+    _set_op_next(s, end, p_next);\n+    _set_op_prev(s, p_next, end);\n+    /* begin.prev -> end.next */\n+    _set_op_next(s, begin_prev, end_next);\n+    _set_op_prev(s, end_next, begin_prev);\n+}\n+\n+/*\n+ * Handles inline_set_label/inline_region_begin/inline_region_end opcodes (which\n+ * will disappear after this optimization).\n+ */\n+static void tcg_inline(TCGContext *s)\n+{\n+    int i;\n+    for (i = 0; i < s->nb_inline_labels; i++) {\n+        TCGInlineLabel *l = &s->inline_labels[i];\n+        size_t region_op_count = l->end_op_idx - l->begin_op_idx - 1;\n+\n+        /* open region is an error */\n+        if (l->begin_op_idx != -1 && l->end_op_idx == -1) {\n+            tcg_abort();\n+        }\n+\n+        if (l->first_point == NULL) {   /* region without points  */\n+            _inline_region_ignore(s, l);\n+        } else if (l->begin_op_idx == -1) { /* points without region */\n+            TCGInlinePoint *p;\n+            for (p = l->first_point; p != NULL; p = p->next_point) {\n+                _inline_point_ignore(s, p);\n+            }\n+        } else if (region_op_count == 0) { /* empty region */\n+            TCGInlinePoint *p;\n+            for (p = l->first_point; p != NULL; p = p->next_point) {\n+                _inline_point_ignore(s, p);\n+            }\n+            _inline_region_ignore(s, l);\n+        } else {                        /* actual inlining */\n+            bool first_point = true;\n+            int l_begin = _get_op_next(s, l->begin_op_idx);\n+            int l_end = _get_op_prev(s, l->end_op_idx);\n+            TCGInlinePoint *p;\n+            for (p = l->first_point; p != NULL; p = p->next_point) {\n+                if (first_point) {\n+                    /* redirect point to existing region (skip markers) */\n+                    _inline_weave(s, p, l_begin, l_end);\n+                    _op_ignore(s, l->begin_op_idx);\n+                    _op_ignore(s, l->end_op_idx);\n+                } else {\n+                    /* create a copy of the region */\n+                    int l_end_next = _get_op_next(s, l_end);\n+                    int op;\n+                    int pos = p->op_idx;\n+                    for (op = l_begin; op != l_end_next;\n+                         op = _get_op_next(s, op)) {\n+                        /* insert opcode copies */\n+                        int insert_idx = s->gen_next_op_idx;\n+                        int opc = s->gen_op_buf[op].opc;\n+                        int args = s->gen_op_buf[op].args;\n+                        int nargs = tcg_op_defs[opc].nb_args;\n+                        if (opc == INDEX_op_call) {\n+                            nargs += s->gen_op_buf[op].calli;\n+                            nargs += s->gen_op_buf[op].callo;\n+                        }\n+                        tcg_op_insert_after(s, &s->gen_op_buf[pos], opc, nargs);\n+                        pos = insert_idx;\n+                        s->gen_op_buf[pos].calli = s->gen_op_buf[op].calli;\n+                        s->gen_op_buf[pos].callo = s->gen_op_buf[op].callo;\n+                        /* insert argument copies */\n+                        memcpy(&s->gen_opparam_buf[s->gen_op_buf[pos].args],\n+                               &s->gen_opparam_buf[args],\n+                               nargs * sizeof(s->gen_opparam_buf[0]));\n+                    }\n+                    _op_ignore(s, p->op_idx);\n+                }\n+                first_point = false;\n+            }\n+        }\n+    }\n+}\n+\n+\n /* Liveness analysis : update the opc_arg_life array to tell if a\n    given input arguments is dead. Instructions updating dead\n    temporaries are removed. */\n@@ -2560,6 +2714,18 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)\n     }\n #endif\n \n+    /* inline code regions before any optimization pass */\n+    tcg_inline(s);\n+\n+#ifdef DEBUG_DISAS\n+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_INLINE)\n+                 && qemu_log_in_addr_range(tb->pc))) {\n+        qemu_log(\"OP after inline:\\n\");\n+        tcg_dump_ops(s);\n+        qemu_log(\"\\n\");\n+    }\n+#endif\n+\n #ifdef CONFIG_PROFILER\n     s->opt_time -= profile_getclock();\n #endif\ndiff --git a/tcg/tcg.h b/tcg/tcg.h\nindex ac94133870..c6e3c6e68d 100644\n--- a/tcg/tcg.h\n+++ b/tcg/tcg.h\n@@ -397,6 +397,20 @@ static inline unsigned get_alignment_bits(TCGMemOp memop)\n \n typedef tcg_target_ulong TCGArg;\n \n+#define TCG_MAX_INLINE_REGIONS 1\n+#define TCG_MAX_INLINE_LABELS TCG_MAX_INLINE_REGIONS\n+\n+typedef struct TCGInlinePoint {\n+    int op_idx;\n+    struct TCGInlinePoint *next_point;\n+} TCGInlinePoint;\n+\n+typedef struct TCGInlineLabel {\n+    TCGInlinePoint *first_point;\n+    int begin_op_idx, end_op_idx;\n+} TCGInlineLabel;\n+\n+\n /* Define type and accessor macros for TCG variables.\n \n    TCG variables are the inputs and outputs of TCG ops, as described\n@@ -649,6 +663,9 @@ struct TCGContext {\n     int nb_temps;\n     int nb_indirects;\n \n+    TCGInlineLabel *inline_labels;\n+    int nb_inline_labels;\n+\n     /* goto_tb support */\n     tcg_insn_unit *code_buf;\n     uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */\n@@ -950,6 +967,7 @@ TCGv_i32 tcg_const_local_i32(int32_t val);\n TCGv_i64 tcg_const_local_i64(int64_t val);\n \n TCGLabel *gen_new_label(void);\n+TCGInlineLabel *gen_new_inline_label(void);\n \n /**\n  * label_arg\ndiff --git a/util/log.c b/util/log.c\nindex 96f30dd21a..947a982c74 100644\n--- a/util/log.c\n+++ b/util/log.c\n@@ -246,6 +246,8 @@ const QEMULogItem qemu_log_items[] = {\n       \"show target assembly code for each compiled TB\" },\n     { CPU_LOG_TB_OP, \"op\",\n       \"show micro ops for each compiled TB\" },\n+    { CPU_LOG_TB_OP_INLINE, \"op_inline\",\n+      \"show micro ops after inlining\" },\n     { CPU_LOG_TB_OP_OPT, \"op_opt\",\n       \"show micro ops after optimization\" },\n     { CPU_LOG_TB_OP_IND, \"op_ind\",\n",
    "prefixes": [
        "4/7"
    ]
}