From 1c8b2efc9ac38c9683366df7e8c7b85866711387 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 16 Dec 2023 21:45:02 +0000 Subject: [PATCH] Avoid repeated bounds evaluation for array-of-array --- src/lower.c | 47 +++++++++++++++++++++++++++++++++-------- test/lower/subtype2.vhd | 8 +++++++ test/test_lower.c | 39 ++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/lower.c b/src/lower.c index 40220f98..86167237 100644 --- a/src/lower.c +++ b/src/lower.c @@ -502,7 +502,8 @@ static vcode_reg_t lower_array_len(lower_unit_t *lu, type_t type, int dim, static vcode_reg_t lower_array_stride(lower_unit_t *lu, type_t type, vcode_reg_t reg) { - vcode_reg_t stride = emit_const(vtype_offset(), 1); + vcode_type_t voffset = vtype_offset(); + vcode_reg_t stride = emit_const(voffset, 1); type_t elem = type_elem(type); if (!type_is_array(elem)) @@ -526,16 +527,20 @@ static vcode_reg_t lower_array_stride(lower_unit_t *lu, type_t type, tree_t r = range_of(elem, i); int64_t low, high; - if (folded_bounds(r, &low, &high)) - len_reg = emit_const(vtype_offset(), MAX(high - low + 1, 0)); + if (!folded_bounds(r, &low, &high)) { + // TODO: this should be a fatal error but lower_type_bounds + // does not work for records - // TODO: this should use lower_get_type_bounds + emit_comment("Workaround for missing record type bounds"); - vcode_reg_t left_reg = lower_range_left(lu, r); - vcode_reg_t right_reg = lower_range_right(lu, r); - vcode_reg_t dir_reg = lower_range_dir(lu, r); + vcode_reg_t left_reg = lower_range_left(lu, r); + vcode_reg_t right_reg = lower_range_right(lu, r); + vcode_reg_t dir_reg = lower_range_dir(lu, r); - len_reg = emit_range_length(left_reg, right_reg, dir_reg); + len_reg = emit_range_length(left_reg, right_reg, dir_reg); + } + else + len_reg = emit_const(voffset, MAX(high - low + 1, 0)); } stride = emit_mul(stride, len_reg); @@ -2755,8 +2760,32 @@ static vcode_reg_t lower_get_type_bounds(lower_unit_t *lu, type_t type) vcode_type_t vtype = lower_type(type); assert(vtype_kind(vtype) == VCODE_TYPE_UARRAY); + const int ndims = vtype_dims(vtype); + int dptr = 0; + vcode_dim_t dims[ndims]; + + const int tdims = dimension_of(type); + for (int i = 0; i < tdims; i++, dptr++) { + tree_t r = range_of(type, i); + dims[dptr].left = lower_range_left(lu, r); + dims[dptr].right = lower_range_right(lu, r); + dims[dptr].dir = lower_range_dir(lu, r); + } + + if (dptr < ndims) { + type_t elem = type_elem(type); + vcode_reg_t bounds_reg = lower_get_type_bounds(lu, elem); + assert(dptr + vtype_dims(vcode_reg_type(bounds_reg)) == ndims); + + for (int i = 0; dptr < ndims; i++, dptr++) { + dims[dptr].left = emit_uarray_left(bounds_reg, i); + dims[dptr].right = emit_uarray_right(bounds_reg, i); + dims[dptr].dir = emit_uarray_dir(bounds_reg, i); + } + } + vcode_reg_t null_reg = emit_null(vtype_pointer(vtype_elem(vtype))); - return lower_wrap(lu, type, null_reg); + return emit_wrap(null_reg, dims, ndims); } } diff --git a/test/lower/subtype2.vhd b/test/lower/subtype2.vhd index 78fc8cbc..43568793 100644 --- a/test/lower/subtype2.vhd +++ b/test/lower/subtype2.vhd @@ -4,6 +4,7 @@ package pack is type t_rec is record f : t_sub1; end record; + type t_nest1 is array (natural range <>) of t_sub1; end package; package body pack is @@ -35,4 +36,11 @@ begin -- begin -- end block; + p1: process is + variable a : t_nest1(1 to 3); + begin + a(1) := "101"; + wait; + end process; + end architecture; diff --git a/test/test_lower.c b/test/test_lower.c index 0fdafa17..2d157a1f 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -4620,12 +4620,12 @@ START_TEST(test_issue462) { VCODE_OP_SELECT }, { VCODE_OP_CAST }, { VCODE_OP_CONST, .value = 8 }, - { VCODE_OP_CONST, .value = 0 }, - { VCODE_OP_CONST, .value = 7 }, - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_MUL }, { VCODE_OP_UNWRAP }, { VCODE_OP_ARRAY_REF }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_CONST, .value = 7 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_DEBUG_LOCUS }, { VCODE_OP_INDEX_CHECK }, { VCODE_OP_CAST }, @@ -5319,14 +5319,14 @@ START_TEST(test_issue756) { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_RANGE_LENGTH }, { VCODE_OP_CONST, .value = 8 }, - { VCODE_OP_CONST, .value = 7 }, - { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_MUL }, { VCODE_OP_NEW }, { VCODE_OP_ALL }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_UNWRAP }, { VCODE_OP_MEMSET }, + { VCODE_OP_CONST, .value = 7 }, + { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_WRAP }, { VCODE_OP_STORE_INDIRECT }, { VCODE_OP_STORE, .name = "PTR" }, @@ -5624,9 +5624,9 @@ START_TEST(test_issue791) vcode_select_unit(vu); EXPECT_BB(0) = { - { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 1048576 }, { VCODE_OP_INDEX, .name = "V_MEMORY" }, + { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_MEMSET }, { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_CONST, .value = 64 }, @@ -5760,6 +5760,33 @@ START_TEST(test_subtype2) CHECK_BB(0); } + + { + vcode_unit_t vu = find_unit("WORK.SUBTYPE2.P1"); + vcode_select_unit(vu); + + EXPECT_BB(0) = { + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 3 }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_LINK_PACKAGE, .name = "WORK.PACK" }, + { VCODE_OP_LINK_VAR, .name = "WORK.PACK.T_SUB1" }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_UARRAY_LEFT }, + { VCODE_OP_UARRAY_RIGHT }, + { VCODE_OP_UARRAY_DIR }, + { VCODE_OP_CONST, .value = 3 }, + { VCODE_OP_RANGE_LENGTH }, + { VCODE_OP_MUL }, + { VCODE_OP_ALLOC }, + { VCODE_OP_WRAP }, + { VCODE_OP_STORE, .name = "A" }, + { VCODE_OP_MEMSET }, + { VCODE_OP_RETURN }, + }; + + CHECK_BB(0); + } } END_TEST -- 2.39.2