diff --git a/src/builder.rs b/src/builder.rs index 5657620879c..481b12d842f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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. + // 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>(