Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 40 additions & 21 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,32 +668,38 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}

fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_add(a, b)
self.assign_to_var(self.gcc_add(a, b))
}

fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a + b
self.assign_to_var(a + b)
}

// TODO(antoyo): should we also override the `unchecked_` versions?
fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sub(a, b)
self.assign_to_var(self.gcc_sub(a, b))
}

fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a - b
self.assign_to_var(a - b)
}

fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_mul(a, b)
self.assign_to_var(self.gcc_mul(a, b))
}

fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.cx.context.new_binary_op(self.location, BinaryOp::Mult, a.get_type(), a, b)
self.assign_to_var(self.cx.context.new_binary_op(
self.location,
BinaryOp::Mult,
a.get_type(),
a,
b,
))
}

fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_udiv(a, b)
self.assign_to_var(self.gcc_udiv(a, b))
}

fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
Expand All @@ -702,11 +708,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
let a = self.gcc_int_cast(a, a_type);
let b_type = b.get_type().to_unsigned(self);
let b = self.gcc_int_cast(b, b_type);
self.gcc_udiv(a, b)
self.assign_to_var(self.gcc_udiv(a, b))
}

fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sdiv(a, b)
self.assign_to_var(self.gcc_sdiv(a, b))
}

fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
Expand All @@ -715,19 +721,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// should be the same.
let typ = a.get_type().to_signed(self);
let b = self.gcc_int_cast(b, typ);
self.gcc_sdiv(a, b)
self.assign_to_var(self.gcc_sdiv(a, b))
}

fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a / b
self.assign_to_var(a / b)
}

fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_urem(a, b)
self.assign_to_var(self.gcc_urem(a, b))
}

fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_srem(a, b)
self.assign_to_var(self.gcc_srem(a, b))
}

fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
Expand Down Expand Up @@ -865,22 +871,26 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {

fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs + rhs)
let result = set_rvalue_location(self, lhs + rhs);
self.assign_to_var(result)
}

fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs - rhs)
let result = set_rvalue_location(self, lhs - rhs);
self.assign_to_var(result)
}

fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs * rhs)
let result = set_rvalue_location(self, lhs * rhs);
self.assign_to_var(result)
}

fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs / rhs)
let result = set_rvalue_location(self, lhs / rhs);
self.assign_to_var(result)
}

fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
Expand All @@ -892,22 +902,22 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {

fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs + rhs
self.assign_to_var(lhs + rhs)
}

fn fsub_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs - rhs
self.assign_to_var(lhs - rhs)
}

fn fmul_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs * rhs
self.assign_to_var(lhs * rhs)
}

fn fdiv_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs / rhs
self.assign_to_var(lhs / rhs)
}

fn frem_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
Expand Down Expand Up @@ -2409,6 +2419,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let res = then_vals | else_vals;
self.bitcast_if_needed(res, result_type)
}

// GCC doesn't like deeply nested expressions.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is due to:

    /* Pre-mark tree nodes with TREE_VISITED so that they can be
       deeply unshared during gimplification (including across
       functions); this requires LANG_HOOKS_DEEP_UNSHARING to be true.  */
    TREE_VISITED (inner) = 1;

In jit-playback.h.

It is NOT GCC that does not like deeply nested expressions BUT rather libgccjit that does not like it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this patch and it doesn't help with memory usage:

From 6e5317dacd4930be53d0ea37de0104d009189319 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sun, 26 Oct 2025 10:06:53 -0400
Subject: [PATCH] Fix TREE_VISITED

---
 gcc/jit/jit-playback.cc | 2 ++
 gcc/jit/jit-playback.h  | 5 ++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index e41408b635c..554057255bc 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -2186,6 +2186,7 @@ get_address (location *loc)
   tree t_thistype = TREE_TYPE (t_lvalue);
   tree t_ptrtype = build_pointer_type (t_thistype);
   tree ptr = fold_build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
+  TREE_VISITED (ptr) = 1;
   if (loc)
     get_context ()->set_tree_location (ptr, loc);
   if (mark_addressable (loc))
@@ -2342,6 +2343,7 @@ playback::function::get_address (location *loc)
   tree t_fndecl = as_fndecl ();
   tree t_fntype = TREE_TYPE (t_fndecl);
   tree t_fnptr = build1 (ADDR_EXPR, build_pointer_type (t_fntype), t_fndecl);
+  TREE_VISITED (t_fnptr) = 1;
   if (loc)
     m_ctxt->set_tree_location (t_fnptr, loc);
   return new rvalue (m_ctxt, t_fnptr);
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 6f297136edc..fb1914e8bc7 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -757,7 +757,10 @@ public:
     /* Pre-mark tree nodes with TREE_VISITED so that they can be
        deeply unshared during gimplification (including across
        functions); this requires LANG_HOOKS_DEEP_UNSHARING to be true.  */
-    TREE_VISITED (inner) = 1;
+    // TODO: try only setting TREE_VISITED on the ADDR_EXPR in
+    // playback::function::get_address and the ADDR_EXPR in
+    // playback::lvalue::get_address.
+    //TREE_VISITED (inner) = 1;
   }
 
   rvalue *
-- 
2.51.1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this helps, the memory usage happens in gimplify_function_tree.

// By assigning intermediate expressions to a variable, this allow us to avoid deeply nested
// expressions and GCC will use much less RAM.
fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> {
let var = self.current_func().new_local(self.location, value.get_type(), "opResult");
self.llbb().add_assignment(self.location, var, value);
var.to_rvalue()
}
}

fn difference_or_zero<'gcc>(
Expand Down