Skip to content

Commit cd97072

Browse files
hiiboltclaude
andcommitted
perf: direct operator emission for scalar RE/LO/ST types
Bypass trait dispatch + Result unwrapping for infallible primitive operations. When both operands are scalar RE, emit direct Rust arithmetic (a + b) instead of RosyAdd::rosy_add(&*a, &*b)?. Also handles LO+LO as ||, LO*LO as &&, ST comparisons, and unary negation. With LTO (--optimized), LLVM was already inlining through the traits, so benchmark impact is minimal there. The real benefit is cleaner generated code, faster non-LTO builds, and laying groundwork for the value-semantics ownership model. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1c44133 commit cd97072

11 files changed

Lines changed: 176 additions & 100 deletions

File tree

rosy/src/program/expressions/operators/arithmetic/add.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,37 +104,46 @@ impl Transpile for AddExpr {
104104
}
105105

106106
// Then, transpile both sides and combine
107-
let mut serialization = String::from("&mut RosyAdd::rosy_add(&*");
108107
let mut errors = Vec::new();
109108
let mut requested_variables = BTreeSet::new();
110109

111110
// Transpile left
112-
match self.left.transpile(context) {
111+
let left_ser = match self.left.transpile(context) {
113112
Ok(output) => {
114-
serialization.push_str(&output.serialization);
115113
requested_variables.extend(output.requested_variables);
114+
output.serialization
116115
},
117116
Err(mut e) => {
118117
for err in e.drain(..) {
119118
errors.push(err.context("...while transpiling left-hand side of addition"));
120119
}
120+
String::new()
121121
}
122-
}
122+
};
123123

124124
// Transpile right
125-
serialization.push_str(", &*");
126-
match self.right.transpile(context) {
125+
let right_ser = match self.right.transpile(context) {
127126
Ok(output) => {
128-
serialization.push_str(&output.serialization);
129127
requested_variables.extend(output.requested_variables);
128+
output.serialization
130129
},
131130
Err(mut e) => {
132131
for err in e.drain(..) {
133132
errors.push(err.context("...while transpiling right-hand side of addition"));
134133
}
134+
String::new()
135135
}
136-
}
137-
serialization.push_str(")?");
136+
};
137+
138+
// Direct emission for infallible scalar types
139+
use crate::rosy_lib::RosyBaseType;
140+
let serialization = match (&left_type.base_type, &right_type.base_type) {
141+
(RosyBaseType::RE, RosyBaseType::RE) if left_type.dimensions == 0 && right_type.dimensions == 0
142+
=> format!("&mut ((*{}) + (*{}))", left_ser, right_ser),
143+
(RosyBaseType::LO, RosyBaseType::LO) if left_type.dimensions == 0 && right_type.dimensions == 0
144+
=> format!("&mut ((*{}) || (*{}))", left_ser, right_ser),
145+
_ => format!("&mut RosyAdd::rosy_add(&*{}, &*{})?", left_ser, right_ser),
146+
};
138147

139148
if errors.is_empty() {
140149
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/arithmetic/div.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,37 +97,44 @@ impl Transpile for DivExpr {
9797
}
9898

9999
// Then, transpile both sides and combine
100-
let mut serialization = String::from("&mut RosyDiv::rosy_div(&*");
101100
let mut errors = Vec::new();
102101
let mut requested_variables = BTreeSet::new();
103102

104103
// Transpile left
105-
match self.left.transpile(context) {
104+
let left_ser = match self.left.transpile(context) {
106105
Ok(output) => {
107-
serialization.push_str(&output.serialization);
108106
requested_variables.extend(output.requested_variables);
107+
output.serialization
109108
},
110109
Err(mut e) => {
111110
for err in e.drain(..) {
112111
errors.push(err.context("...while transpiling left-hand side of division"));
113112
}
113+
String::new()
114114
}
115-
}
115+
};
116116

117117
// Transpile right
118-
serialization.push_str(", &*");
119-
match self.right.transpile(context) {
118+
let right_ser = match self.right.transpile(context) {
120119
Ok(output) => {
121-
serialization.push_str(&output.serialization);
122120
requested_variables.extend(output.requested_variables);
121+
output.serialization
123122
},
124123
Err(mut e) => {
125124
for err in e.drain(..) {
126125
errors.push(err.context("...while transpiling right-hand side of division"));
127126
}
127+
String::new()
128128
}
129-
}
130-
serialization.push_str(")?");
129+
};
130+
131+
// Direct emission for infallible scalar types
132+
use crate::rosy_lib::RosyBaseType;
133+
let serialization = match (&left_type.base_type, &right_type.base_type) {
134+
(RosyBaseType::RE, RosyBaseType::RE) if left_type.dimensions == 0 && right_type.dimensions == 0
135+
=> format!("&mut ((*{}) / (*{}))", left_ser, right_ser),
136+
_ => format!("&mut RosyDiv::rosy_div(&*{}, &*{})?", left_ser, right_ser),
137+
};
131138

132139
if errors.is_empty() {
133140
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/arithmetic/mult.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,37 +99,46 @@ impl Transpile for MultExpr {
9999
}
100100

101101
// Then, transpile both sides and combine
102-
let mut serialization = String::from("&mut RosyMult::rosy_mult(&*");
103102
let mut errors = Vec::new();
104103
let mut requested_variables = BTreeSet::new();
105104

106105
// Transpile left
107-
match self.left.transpile(context) {
106+
let left_ser = match self.left.transpile(context) {
108107
Ok(output) => {
109-
serialization.push_str(&output.serialization);
110108
requested_variables.extend(output.requested_variables);
109+
output.serialization
111110
},
112111
Err(mut e) => {
113112
for err in e.drain(..) {
114113
errors.push(err.context("...while transpiling left-hand side of multiplication"));
115114
}
115+
String::new()
116116
}
117-
}
117+
};
118118

119119
// Transpile right
120-
serialization.push_str(", &*");
121-
match self.right.transpile(context) {
120+
let right_ser = match self.right.transpile(context) {
122121
Ok(output) => {
123-
serialization.push_str(&output.serialization);
124122
requested_variables.extend(output.requested_variables);
123+
output.serialization
125124
},
126125
Err(mut e) => {
127126
for err in e.drain(..) {
128127
errors.push(err.context("...while transpiling right-hand side of multiplication"));
129128
}
129+
String::new()
130130
}
131-
}
132-
serialization.push_str(")?");
131+
};
132+
133+
// Direct emission for infallible scalar types
134+
use crate::rosy_lib::RosyBaseType;
135+
let serialization = match (&left_type.base_type, &right_type.base_type) {
136+
(RosyBaseType::RE, RosyBaseType::RE) if left_type.dimensions == 0 && right_type.dimensions == 0
137+
=> format!("&mut ((*{}) * (*{}))", left_ser, right_ser),
138+
(RosyBaseType::LO, RosyBaseType::LO) if left_type.dimensions == 0 && right_type.dimensions == 0
139+
=> format!("&mut ((*{}) && (*{}))", left_ser, right_ser),
140+
_ => format!("&mut RosyMult::rosy_mult(&*{}, &*{})?", left_ser, right_ser),
141+
};
133142

134143
if errors.is_empty() {
135144
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/arithmetic/sub.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,37 +97,44 @@ impl Transpile for SubExpr {
9797
}
9898

9999
// Then, transpile both sides and combine
100-
let mut serialization = String::from("&mut RosySub::rosy_sub(&*");
101100
let mut errors = Vec::new();
102101
let mut requested_variables = BTreeSet::new();
103102

104103
// Transpile left
105-
match self.left.transpile(context) {
104+
let left_ser = match self.left.transpile(context) {
106105
Ok(output) => {
107-
serialization.push_str(&output.serialization);
108106
requested_variables.extend(output.requested_variables);
107+
output.serialization
109108
},
110109
Err(mut e) => {
111110
for err in e.drain(..) {
112111
errors.push(err.context("...while transpiling left-hand side of subtraction"));
113112
}
113+
String::new()
114114
}
115-
}
115+
};
116116

117117
// Transpile right
118-
serialization.push_str(", &*");
119-
match self.right.transpile(context) {
118+
let right_ser = match self.right.transpile(context) {
120119
Ok(output) => {
121-
serialization.push_str(&output.serialization);
122120
requested_variables.extend(output.requested_variables);
121+
output.serialization
123122
},
124123
Err(mut e) => {
125124
for err in e.drain(..) {
126125
errors.push(err.context("...while transpiling right-hand side of subtraction"));
127126
}
127+
String::new()
128128
}
129-
}
130-
serialization.push_str(")?");
129+
};
130+
131+
// Direct emission for infallible scalar types
132+
use crate::rosy_lib::RosyBaseType;
133+
let serialization = match (&left_type.base_type, &right_type.base_type) {
134+
(RosyBaseType::RE, RosyBaseType::RE) if left_type.dimensions == 0 && right_type.dimensions == 0
135+
=> format!("&mut ((*{}) - (*{}))", left_ser, right_ser),
136+
_ => format!("&mut RosySub::rosy_sub(&*{}, &*{})?", left_ser, right_ser),
137+
};
131138

132139
if errors.is_empty() {
133140
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/comparison/eq.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,37 +78,42 @@ impl Transpile for EqExpr {
7878
}
7979

8080
// Then, transpile both sides and combine
81-
let mut serialization = String::from("&mut RosyEq::rosy_eq(&*");
8281
let mut errors = Vec::new();
8382
let mut requested_variables = BTreeSet::new();
8483

85-
// Transpile left
86-
match self.left.transpile(context) {
84+
let left_ser = match self.left.transpile(context) {
8785
Ok(output) => {
88-
serialization.push_str(&output.serialization);
8986
requested_variables.extend(output.requested_variables);
87+
output.serialization
9088
},
9189
Err(mut e) => {
9290
for err in e.drain(..) {
9391
errors.push(err.context("...while transpiling left-hand side of equality"));
9492
}
93+
String::new()
9594
}
96-
}
95+
};
9796

98-
// Transpile right
99-
serialization.push_str(", &*");
100-
match self.right.transpile(context) {
97+
let right_ser = match self.right.transpile(context) {
10198
Ok(output) => {
102-
serialization.push_str(&output.serialization);
10399
requested_variables.extend(output.requested_variables);
100+
output.serialization
104101
},
105102
Err(mut e) => {
106103
for err in e.drain(..) {
107104
errors.push(err.context("...while transpiling right-hand side of equality"));
108105
}
106+
String::new()
109107
}
110-
}
111-
serialization.push_str(")?");
108+
};
109+
110+
use crate::rosy_lib::RosyBaseType;
111+
let serialization = match (&left_type.base_type, &right_type.base_type) {
112+
(RosyBaseType::RE, RosyBaseType::RE) | (RosyBaseType::ST, RosyBaseType::ST)
113+
if left_type.dimensions == 0 && right_type.dimensions == 0
114+
=> format!("&mut ((*{}) == (*{}))", left_ser, right_ser),
115+
_ => format!("&mut RosyEq::rosy_eq(&*{}, &*{})?", left_ser, right_ser),
116+
};
112117

113118
if errors.is_empty() {
114119
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/comparison/gt.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,42 @@ impl Transpile for GtExpr {
6666
)));
6767
}
6868

69-
let mut serialization = String::from("&mut RosyGt::rosy_gt(&*");
7069
let mut errors = Vec::new();
7170
let mut requested_variables = BTreeSet::new();
7271

73-
match self.left.transpile(context) {
72+
let left_ser = match self.left.transpile(context) {
7473
Ok(output) => {
75-
serialization.push_str(&output.serialization);
7674
requested_variables.extend(output.requested_variables);
75+
output.serialization
7776
},
7877
Err(mut e) => {
7978
for err in e.drain(..) {
8079
errors.push(err.context("...while transpiling left-hand side of greater-than"));
8180
}
81+
String::new()
8282
}
83-
}
83+
};
8484

85-
serialization.push_str(", &*");
86-
match self.right.transpile(context) {
85+
let right_ser = match self.right.transpile(context) {
8786
Ok(output) => {
88-
serialization.push_str(&output.serialization);
8987
requested_variables.extend(output.requested_variables);
88+
output.serialization
9089
},
9190
Err(mut e) => {
9291
for err in e.drain(..) {
9392
errors.push(err.context("...while transpiling right-hand side of greater-than"));
9493
}
94+
String::new()
9595
}
96-
}
97-
serialization.push_str(")?");
96+
};
97+
98+
use crate::rosy_lib::RosyBaseType;
99+
let serialization = match (&left_type.base_type, &right_type.base_type) {
100+
(RosyBaseType::RE, RosyBaseType::RE) | (RosyBaseType::ST, RosyBaseType::ST)
101+
if left_type.dimensions == 0 && right_type.dimensions == 0
102+
=> format!("&mut ((*{}) > (*{}))", left_ser, right_ser),
103+
_ => format!("&mut RosyGt::rosy_gt(&*{}, &*{})?", left_ser, right_ser),
104+
};
98105

99106
if errors.is_empty() {
100107
Ok(TranspilationOutput {

rosy/src/program/expressions/operators/comparison/gte.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,42 @@ impl Transpile for GteExpr {
6666
)));
6767
}
6868

69-
let mut serialization = String::from("&mut RosyGte::rosy_gte(&*");
7069
let mut errors = Vec::new();
7170
let mut requested_variables = BTreeSet::new();
7271

73-
match self.left.transpile(context) {
72+
let left_ser = match self.left.transpile(context) {
7473
Ok(output) => {
75-
serialization.push_str(&output.serialization);
7674
requested_variables.extend(output.requested_variables);
75+
output.serialization
7776
},
7877
Err(mut e) => {
7978
for err in e.drain(..) {
8079
errors.push(err.context("...while transpiling left-hand side of greater-than-or-equal"));
8180
}
81+
String::new()
8282
}
83-
}
83+
};
8484

85-
serialization.push_str(", &*");
86-
match self.right.transpile(context) {
85+
let right_ser = match self.right.transpile(context) {
8786
Ok(output) => {
88-
serialization.push_str(&output.serialization);
8987
requested_variables.extend(output.requested_variables);
88+
output.serialization
9089
},
9190
Err(mut e) => {
9291
for err in e.drain(..) {
9392
errors.push(err.context("...while transpiling right-hand side of greater-than-or-equal"));
9493
}
94+
String::new()
9595
}
96-
}
97-
serialization.push_str(")?");
96+
};
97+
98+
use crate::rosy_lib::RosyBaseType;
99+
let serialization = match (&left_type.base_type, &right_type.base_type) {
100+
(RosyBaseType::RE, RosyBaseType::RE) | (RosyBaseType::ST, RosyBaseType::ST)
101+
if left_type.dimensions == 0 && right_type.dimensions == 0
102+
=> format!("&mut ((*{}) >= (*{}))", left_ser, right_ser),
103+
_ => format!("&mut RosyGte::rosy_gte(&*{}, &*{})?", left_ser, right_ser),
104+
};
98105

99106
if errors.is_empty() {
100107
Ok(TranspilationOutput {

0 commit comments

Comments
 (0)