From c0259ea6c2d2df3a7a8313b54c7b1f1466a54d7b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 5 Nov 2022 22:00:53 +0000 Subject: [PATCH] Skip generating aggregates with null ranges. Fixes #560 --- src/lower.c | 25 +++- test/regress/issue560.vhd | 274 ++++++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + test/test_lower.c | 17 ++- 4 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 test/regress/issue560.vhd diff --git a/src/lower.c b/src/lower.c index 9a622769..27961cc6 100644 --- a/src/lower.c +++ b/src/lower.c @@ -3289,9 +3289,14 @@ static vcode_reg_t lower_array_aggregate(tree_t expr, vcode_reg_t hint) vcode_type_t vbounds = lower_bounds(scalar_elem_type); int64_t null_const; - if (vcode_reg_const(null_reg, &null_const) && null_const) { - vcode_type_t vtype = vtype_carray(0, velem, vbounds); - return emit_address_of(emit_const_array(vtype, NULL, 0)); + bool known_not_null = false; + if (vcode_reg_const(null_reg, &null_const)) { + if (null_const) { + vcode_type_t vtype = vtype_carray(0, velem, vbounds); + return emit_address_of(emit_const_array(vtype, NULL, 0)); + } + else + known_not_null = true; } vcode_type_t voffset = vtype_offset(); @@ -3367,6 +3372,15 @@ static vcode_reg_t lower_array_aggregate(tree_t expr, vcode_reg_t hint) wrap_reg = emit_wrap(mem_reg, &dim0, 1); } + vcode_block_t skip_bb = VCODE_INVALID_BLOCK; + if (!known_not_null) { + vcode_block_t not_null_bb = emit_block(); + skip_bb = emit_block(); + emit_cond(null_reg, skip_bb, not_null_bb); + + vcode_select_block(not_null_bb); + } + if (def_value != NULL) { // Initialise the array with the default value if (type_is_scalar(elem_type) && !multidim) { @@ -3608,6 +3622,11 @@ static vcode_reg_t lower_array_aggregate(tree_t expr, vcode_reg_t hint) lower_release_temp(tmp_var); } + if (skip_bb != VCODE_INVALID_BLOCK) { + emit_jump(skip_bb); + vcode_select_block(skip_bb); + } + return wrap_reg; } diff --git a/test/regress/issue560.vhd b/test/regress/issue560.vhd new file mode 100644 index 00000000..e2689f16 --- /dev/null +++ b/test/regress/issue560.vhd @@ -0,0 +1,274 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package test_pkg is + type t_axi_wr_slave_in_if is record + awid : std_logic_vector; + awaddr : std_logic_vector; + awlen : std_logic_vector(7 downto 0); + awsize : std_logic_vector(2 downto 0); + awburst : std_logic_vector(1 downto 0); + awlock : std_logic; + awcache : std_logic_vector(3 downto 0); + awprot : std_logic_vector(2 downto 0); + awqos : std_logic_vector(3 downto 0); + awregion : std_logic_vector(3 downto 0); + awuser : std_logic_vector; + awvalid : std_logic; + wdata : std_logic_vector; + wstrb : std_logic_vector; + wlast : std_logic; + wuser : std_logic_vector; + wvalid : std_logic; + bready : std_logic; + end record; + type t_axi_wr_slave_out_if is record + awready : std_logic; + wready : std_logic; + bid : std_logic_vector; + bresp : std_logic_vector(1 downto 0); + buser : std_logic_vector; + bvalid : std_logic; + end record; + type t_axi_rd_slave_in_if is record + arid : std_logic_vector; + araddr : std_logic_vector; + arlen : std_logic_vector(7 downto 0); + arsize : std_logic_vector(2 downto 0); + arburst : std_logic_vector(1 downto 0); + arlock : std_logic; + arcache : std_logic_vector(3 downto 0); + arprot : std_logic_vector(2 downto 0); + arqos : std_logic_vector(3 downto 0); + arregion : std_logic_vector(3 downto 0); + aruser : std_logic_vector; + arvalid : std_logic; + rready : std_logic; + end record; + type t_axi_rd_slave_out_if is record + arready : std_logic; + rid : std_logic_vector; + rdata : std_logic_vector; + rresp : std_logic_vector(1 downto 0); + rlast : std_logic; + ruser : std_logic_vector; + rvalid : std_logic; + end record; + + type t_axi_write_address_channel is record + awid : std_logic_vector; + awaddr : std_logic_vector; + awlen : std_logic_vector(7 downto 0); + awsize : std_logic_vector(2 downto 0); + awburst : std_logic_vector(1 downto 0); + awlock : std_logic; + awcache : std_logic_vector(3 downto 0); + awprot : std_logic_vector(2 downto 0); + awqos : std_logic_vector(3 downto 0); + awregion : std_logic_vector(3 downto 0); + awuser : std_logic_vector; + awvalid : std_logic; + awready : std_logic; + end record; + + type t_axi_write_data_channel is record + wdata : std_logic_vector; + wstrb : std_logic_vector; + wlast : std_logic; + wuser : std_logic_vector; + wvalid : std_logic; + wready : std_logic; + end record; + + type t_axi_write_response_channel is record + bid : std_logic_vector; + bresp : std_logic_vector(1 downto 0); + buser : std_logic_vector; + bvalid : std_logic; + bready : std_logic; + end record; + + type t_axi_read_address_channel is record + arid : std_logic_vector; + araddr : std_logic_vector; + arlen : std_logic_vector(7 downto 0); + arsize : std_logic_vector(2 downto 0); + arburst : std_logic_vector(1 downto 0); + arlock : std_logic; + arcache : std_logic_vector(3 downto 0); + arprot : std_logic_vector(2 downto 0); + arqos : std_logic_vector(3 downto 0); + arregion : std_logic_vector(3 downto 0); + aruser : std_logic_vector; + arvalid : std_logic; + arready : std_logic; + end record; + + type t_axi_read_data_channel is record + rid : std_logic_vector; + rdata : std_logic_vector; + rresp : std_logic_vector(1 downto 0); + rlast : std_logic; + ruser : std_logic_vector; + rvalid : std_logic; + rready : std_logic; + end record; + + type t_axi_if is record + write_address_channel : t_axi_write_address_channel; + write_data_channel : t_axi_write_data_channel; + write_response_channel : t_axi_write_response_channel; + read_address_channel : t_axi_read_address_channel; + read_data_channel : t_axi_read_data_channel; + end record; +end package; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.test_pkg.all; + +entity test2 is + port ( + wr_port_in : in t_axi_wr_slave_in_if; + wr_port_out : out t_axi_wr_slave_out_if; + rd_port_in : in t_axi_rd_slave_in_if; + rd_port_out : out t_axi_rd_slave_out_if + ); +end entity test2; +architecture beh of test2 is +signal clk : std_logic; +signal reset_n : std_logic := '1'; +begin +p1: process(clk, reset_n) +begin + if reset_n = '1' then + wr_port_out.bid <= (wr_port_out.bid'range => '0'); + rd_port_out.rid <= (rd_port_out.rid'range => '0'); + elsif rising_edge(clk) then + null; + end if; +end process; +end architecture beh; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.test_pkg.all; + +entity test3 is + generic( + GC_ADDR_WIDTH_1 : natural := 32; + GC_DATA_WIDTH_1 : natural := 32; + GC_ID_WIDTH_1 : natural := 8; + GC_USER_WIDTH_1 : natural := 8 + ); +end entity test3; +architecture beh of test3 is + signal axi_if : t_axi_if( write_address_channel( awid( GC_ID_WIDTH_1 -1 downto 0), + awaddr( GC_ADDR_WIDTH_1-1 downto 0), + awuser( GC_USER_WIDTH_1 -1 downto 0)), + write_data_channel( wdata( GC_DATA_WIDTH_1-1 downto 0), + wstrb( GC_DATA_WIDTH_1/8 -1 downto 0), + wuser( GC_USER_WIDTH_1 -1 downto 0)), + write_response_channel(bid( GC_ID_WIDTH_1 -1 downto 0), + buser( GC_USER_WIDTH_1 -1 downto 0)), + read_address_channel( arid( GC_ID_WIDTH_1 -1 downto 0), + araddr( GC_ADDR_WIDTH_1-1 downto 0), + aruser( GC_USER_WIDTH_1-1 downto 0)), + read_data_channel( rid( GC_ID_WIDTH_1-1 downto 0), + rdata( GC_DATA_WIDTH_1-1 downto 0), + ruser( GC_USER_WIDTH_1-1 downto 0))); +begin + i_test : entity work.test2 + port map ( + --aclk => clk, + --aresetn => aresetn, + -- Inputs + -- write address channel + wr_port_in.awid => axi_if.write_address_channel.awid, + wr_port_in.awaddr => axi_if.write_address_channel.awaddr, + wr_port_in.awlen => axi_if.write_address_channel.awlen, + wr_port_in.awsize => axi_if.write_address_channel.awsize, + wr_port_in.awburst => axi_if.write_address_channel.awburst, + wr_port_in.awlock => axi_if.write_address_channel.awlock, + wr_port_in.awcache => axi_if.write_address_channel.awcache, + wr_port_in.awprot => axi_if.write_address_channel.awprot, + wr_port_in.awqos => axi_if.write_address_channel.awqos, + wr_port_in.awregion => axi_if.write_address_channel.awregion, + wr_port_in.awuser => axi_if.write_address_channel.awuser, + wr_port_in.awvalid => axi_if.write_address_channel.awvalid, + -- write data channel + wr_port_in.wdata => axi_if.write_data_channel.wdata, + wr_port_in.wstrb => axi_if.write_data_channel.wstrb, + wr_port_in.wlast => axi_if.write_data_channel.wlast, + wr_port_in.wuser => axi_if.write_data_channel.wuser, + wr_port_in.wvalid => axi_if.write_data_channel.wvalid, + -- write response channel + wr_port_in.bready => axi_if.write_response_channel.bready, + -- read address channel + rd_port_in.arid => axi_if.read_address_channel.arid, + rd_port_in.araddr => axi_if.read_address_channel.araddr, + rd_port_in.arlen => axi_if.read_address_channel.arlen, + rd_port_in.arsize => axi_if.read_address_channel.arsize, + rd_port_in.arburst => axi_if.read_address_channel.arburst, + rd_port_in.arlock => axi_if.read_address_channel.arlock, + rd_port_in.arcache => axi_if.read_address_channel.arcache, + rd_port_in.arprot => axi_if.read_address_channel.arprot, + rd_port_in.arqos => axi_if.read_address_channel.arqos, + rd_port_in.arregion => axi_if.read_address_channel.arregion, + rd_port_in.aruser => axi_if.read_address_channel.aruser, + rd_port_in.arvalid => axi_if.read_address_channel.arvalid, + -- read data channel + rd_port_in.rready => axi_if.read_data_channel.rready, + -- Outputs + -- write address channel + wr_port_out.awready => axi_if.write_address_channel.awready, + -- write data channel + wr_port_out.wready => axi_if.write_data_channel.wready, + -- write response channel + wr_port_out.bid => axi_if.write_response_channel.bid, + wr_port_out.bresp => axi_if.write_response_channel.bresp, + wr_port_out.buser => axi_if.write_response_channel.buser, + wr_port_out.bvalid => axi_if.write_response_channel.bvalid, + -- read address channel + rd_port_out.arready => axi_if.read_address_channel.arready, + -- read data channel + rd_port_out.rid => axi_if.read_data_channel.rid, + rd_port_out.rdata => axi_if.read_data_channel.rdata, + rd_port_out.rresp => axi_if.read_data_channel.rresp, + rd_port_out.rlast => axi_if.read_data_channel.rlast, + rd_port_out.ruser => axi_if.read_data_channel.ruser, + rd_port_out.rvalid => axi_if.read_data_channel.rvalid + ); + + process + begin + report "OK"; + wait; + end process; + +end architecture beh; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.test_pkg.all; + +entity issue560 is +end entity issue560; +architecture beh of issue560 is + constant C_ADDR_WIDTH_1 : natural := 32; + constant C_DATA_WIDTH_1 : natural := 32; + constant C_ID_WIDTH_1 : natural := 0; + constant C_USER_WIDTH_1 : natural := 8; +begin + i_test3 : entity work.test3 + generic map ( + GC_ADDR_WIDTH_1 => C_ADDR_WIDTH_1, + GC_DATA_WIDTH_1 => C_DATA_WIDTH_1, + GC_ID_WIDTH_1 => C_ID_WIDTH_1, + GC_USER_WIDTH_1 => C_USER_WIDTH_1 + ); +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 34d64b21..3bf5aa9f 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -687,3 +687,4 @@ issue549 normal case14 normal,2008 cmdline4 shell record38 fail,gold,2008 +issue560 normal,2008 diff --git a/test/test_lower.c b/test/test_lower.c index aaec5b4a..f8daf8f1 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -3712,11 +3712,26 @@ START_TEST(test_vital2) { VCODE_OP_RANGE_LENGTH }, { VCODE_OP_ALLOC }, { VCODE_OP_WRAP }, - { VCODE_OP_STORE, .name = "*i" }, { VCODE_OP_COND, .target = 2, .target_else = 1 }, }; CHECK_BB(0); + + EXPECT_BB(1) = { + { VCODE_OP_UARRAY_LEFT }, + { VCODE_OP_UARRAY_RIGHT }, + { VCODE_OP_UARRAY_DIR }, + { VCODE_OP_CAST }, + { VCODE_OP_CAST }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_INDEX_CHECK }, // TODO: redundant + { VCODE_OP_INDEX_CHECK }, // TODO: redundant + { VCODE_OP_STORE, .name = "*i" }, + { VCODE_OP_RANGE_NULL }, + { VCODE_OP_COND, .target = 4, .target_else = 3 }, + }; + + CHECK_BB(1); } END_TEST -- 2.39.2