aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-07-07 11:13:20 +0100
committergingerBill <bill@gingerbill.org>2018-07-07 11:13:20 +0100
commitfa4e95105f7364367dce8ac435efed182fba6759 (patch)
tree38b24ae823fb516b70be2a86126be09704b3c6d8 /src/ir.cpp
parent1e01085ef7a921f7e83d63c27d56e18716ab2e68 (diff)
Loop array arithmetic on large arrays
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 9103b5491..c98cec5f4 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -2192,6 +2192,8 @@ irValue *ir_map_cap(irProcedure *proc, irValue *value) {
+void ir_emit_increment(irProcedure *proc, irValue *addr);
+irValue *ir_emit_array_ep(irProcedure *proc, irValue *s, irValue *index);
irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index);
irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index);
@@ -2253,11 +2255,43 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
irValue *res = ir_add_local_generated(proc, type);
i64 count = base_type(type)->Array.count;
- for (i32 i = 0; i < count; i++) {
- irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i));
- irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i));
+
+ bool inline_array_arith = type_size_of(type) <= build_context.max_align;
+
+ if (inline_array_arith) {
+ // inline
+ for (i32 i = 0; i < count; i++) {
+ irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i));
+ irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i));
+ irValue *z = ir_emit_arith(proc, op, x, y, elem_type);
+ ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z);
+ }
+ } else {
+ irValue *idx_addr = ir_add_local_generated(proc, t_int);
+ irValue *max = ir_const_int(proc->module->allocator, count);
+
+ irBlock *body = ir_new_block(proc, nullptr, "array.arith.body");
+ irBlock *done = ir_new_block(proc, nullptr, "array.arith.done");
+ irBlock *loop = ir_new_block(proc, nullptr, "array.arith.loop");
+
+ ir_emit_jump(proc, loop);
+ ir_start_block(proc, loop);
+
+ irValue *idx = ir_emit_load(proc, idx_addr);
+
+ irValue *cond = ir_emit_comp(proc, Token_Lt, idx, max);
+ ir_emit_if(proc, cond, body, done);
+ ir_start_block(proc, body);
+
+ irValue *x = ir_emit_load(proc, ir_emit_array_ep(proc, lhs, idx));
+ irValue *y = ir_emit_load(proc, ir_emit_array_ep(proc, rhs, idx));
irValue *z = ir_emit_arith(proc, op, x, y, elem_type);
- ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z);
+ ir_emit_store(proc, ir_emit_array_ep(proc, res, idx), z);
+
+ ir_emit_increment(proc, idx_addr);
+ ir_emit_jump(proc, loop);
+
+ ir_start_block(proc, done);
}
ir_emit_comment(proc, str_lit("array.arith.end"));
return ir_emit_load(proc, res);