[DTrace-devel] [PATCH 3/3] cg: optimize ternary expressions for strings
Kris Van Hees
kris.van.hees at oracle.com
Tue Jul 15 19:50:51 UTC 2025
If either size of a ternary expression has a tstring value, it can be
re-used to store the value of the ternary expression, reducing the
need for tstring allocation, especially in nested ternaries.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_cg.c | 56 +++++++++++++++----
libdtrace/dt_impl.h | 2 +-
.../codegen/tst.tstring_ternary_mix.d | 30 ++++++++++
.../codegen/tst.tstring_ternary_mix.r | 1 +
.../codegen/tst.tstring_ternary_nested.d | 26 +++++++++
.../codegen/tst.tstring_ternary_nested.r | 1 +
6 files changed, 105 insertions(+), 11 deletions(-)
create mode 100644 test/unittest/codegen/tst.tstring_ternary_mix.d
create mode 100644 test/unittest/codegen/tst.tstring_ternary_mix.r
create mode 100644 test/unittest/codegen/tst.tstring_ternary_nested.d
create mode 100644 test/unittest/codegen/tst.tstring_ternary_nested.r
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 6c7ad076..11c94a5e 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -4630,29 +4630,65 @@ dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
* dn_right).
*/
if (dt_node_is_string(dnp)) {
- uint_t lbl_null = dt_irlist_label(dlp);
+ uint_t lbl_done = dt_irlist_label(dlp);
+ int left_is_tstr, rght_is_tstr;
- emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_reg, 0, lbl_null));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_reg, 0, lbl_done));
/*
- * At this point, dnp->dn_reg holds a pointer to the string we
- * need to copy. But we want to copy it into a tstring which
- * location is to be stored in dnp->dn_reg. So, we need to
- * shuffle things a bit.
+ * At this point, dnp->dn_reg holds a pointer to the string to
+ * be used as value of the ternary. It needs to be made
+ * available as a tstring.
+ * If dnp->dn_left is a tstring, reuse it as tstring for the
+ * ternary value.
+ * If dnp->dn_left is not a tstring but dnp->dn_right is, use
+ * that one as tstring for the ternary value.
+ * Otherwise, allocate a tstring.
+ *
+ * Either way, we copy the value (a string) into the tstring
+ * (unless it is already there).
*/
emit(dlp, BPF_MOV_REG(BPF_REG_0, dnp->dn_reg));
- dt_cg_tstring_alloc(yypcb, dnp);
+
+ left_is_tstr = dt_node_is_tstring(dnp->dn_left);
+ rght_is_tstr = dt_node_is_tstring(dnp->dn_right);
+
+ if (left_is_tstr)
+ dnp->dn_tstring = dnp->dn_left->dn_tstring;
+ else if (rght_is_tstr)
+ dnp->dn_tstring = dnp->dn_right->dn_tstring;
+ else
+ dt_cg_tstring_alloc(yypcb, dnp);
dt_cg_access_dctx(dnp->dn_reg, dlp, drp, DCTX_MEM);
emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
+ emit(dlp, BPF_BRANCH_REG(BPF_JEQ, dnp->dn_reg, BPF_REG_0, lbl_done));
+
dt_cg_memcpy(dlp, drp, dnp->dn_reg, BPF_REG_0,
yypcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE]);
- emitl(dlp, lbl_null,
+ emitl(dlp, lbl_done,
BPF_NOP());
- dt_cg_tstring_free(yypcb, dnp->dn_left);
- dt_cg_tstring_free(yypcb, dnp->dn_right);
+
+ /*
+ * Free the (possible) tstrings for left and right children.
+ * If a child is a tstring and that tstring is being reused for
+ * the ternary value, simply set dn_tstring to NULL. Otherwise
+ * truly free it.
+ */
+ if (left_is_tstr) {
+ if (dnp->dn_tstring != dnp->dn_left->dn_tstring)
+ dt_cg_tstring_free(yypcb, dnp->dn_left);
+ else
+ dnp->dn_left->dn_tstring = NULL;
+ }
+ if (rght_is_tstr) {
+ if (dnp->dn_tstring != dnp->dn_right->dn_tstring)
+ dt_cg_tstring_free(yypcb, dnp->dn_right);
+ else
+ dnp->dn_right->dn_tstring = NULL;
+ }
}
}
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 2adc1252..c6d9e782 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -222,7 +222,7 @@ typedef struct dt_kern_path {
* - cleanpath() holds a prepended '/' char, a string, an appended '/' char,
* and a terminating NUL char, or STRSZ + 3 chars altogether
*/
-#define DT_TSTRING_SLOTS 4
+#define DT_TSTRING_SLOTS 6
#define DT_TSTRING_SIZE(dtp) \
MAX(P2ROUNDUP((dtp)->dt_options[DTRACEOPT_STRSIZE] + 3, 8), \
72)
diff --git a/test/unittest/codegen/tst.tstring_ternary_mix.d b/test/unittest/codegen/tst.tstring_ternary_mix.d
new file mode 100644
index 00000000..0123c428
--- /dev/null
+++ b/test/unittest/codegen/tst.tstring_ternary_mix.d
@@ -0,0 +1,30 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * Ensure tstrings are handled correctly for ternary (?:) expressions.
+ */
+
+#pragma D option quiet
+
+BEGIN {
+ a = 1;
+ b = 2;
+ trace(a != b ? "abcdef" : "ABCDEF");
+ trace(" ");
+ trace(a > b ? strjoin("abc", "def") : "ABCDEF");
+ trace(" ");
+ trace(a < b ? "abcdef" : strjoin("ABC", "DEF"));
+ trace(" ");
+ trace(a == b ? strjoin("abc", "def") : strjoin("ABC", "DEF"));
+
+ exit(0);
+}
+
+ERROR {
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.tstring_ternary_mix.r b/test/unittest/codegen/tst.tstring_ternary_mix.r
new file mode 100644
index 00000000..72cc85c3
--- /dev/null
+++ b/test/unittest/codegen/tst.tstring_ternary_mix.r
@@ -0,0 +1 @@
+abcdef ABCDEF abcdef ABCDEF
diff --git a/test/unittest/codegen/tst.tstring_ternary_nested.d b/test/unittest/codegen/tst.tstring_ternary_nested.d
new file mode 100644
index 00000000..8cd2ea60
--- /dev/null
+++ b/test/unittest/codegen/tst.tstring_ternary_nested.d
@@ -0,0 +1,26 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * Ensure tstrings are handled correctly for nested ternary (?:) expressions.
+ */
+
+#pragma D option quiet
+
+BEGIN {
+ x = 42;
+ trace(x > 1 ? strjoin(strjoin("a", "bc"), strjoin("de", "f")) :
+ x > 2 ? strjoin(strjoin("A", "BC"), strjoin("DE", "F")) :
+ x > 3 ? strjoin(strjoin("u", "vw"), strjoin("xy", "z")) :
+ strjoin(strjoin("U", "VW"), strjoin("XY", "Z")));
+
+ exit(0);
+}
+
+ERROR {
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.tstring_ternary_nested.r b/test/unittest/codegen/tst.tstring_ternary_nested.r
new file mode 100644
index 00000000..0373d933
--- /dev/null
+++ b/test/unittest/codegen/tst.tstring_ternary_nested.r
@@ -0,0 +1 @@
+abcdef
--
2.45.2
More information about the DTrace-devel
mailing list