Refining shape iterator optimization, so it checks instances for overlap with shapes rather the other way round. This suits better to real test cases.

This commit is contained in:
Matthias Koefferlein 2024-03-27 23:46:33 +01:00
parent 5699c91d3f
commit cb5a1f7d3e
3 changed files with 41 additions and 37 deletions

View File

@ -680,13 +680,17 @@ bool run_tiled_xor (const XORData &xor_data)
if (ll->second.first < 0) {
proc.input (in_a, db::RecursiveShapeIterator ());
} else {
proc.input (in_a, db::RecursiveShapeIterator (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first));
db::RecursiveShapeIterator si (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first);
si.set_for_merged_input (true);
proc.input (in_a, si);
}
if (ll->second.second < 0) {
proc.input (in_b, db::RecursiveShapeIterator ());
} else {
proc.input (in_b, db::RecursiveShapeIterator (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second));
db::RecursiveShapeIterator si (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second);
si.set_for_merged_input (true);
proc.input (in_b, si);
}
std::string expr = "var x=" + in_a + "^" + in_b + "; ";
@ -805,10 +809,12 @@ bool run_deep_xor (const XORData &xor_data)
if (ll->second.first >= 0) {
ri_a = db::RecursiveShapeIterator (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first);
ri_a.set_for_merged_input (true);
}
if (ll->second.second >= 0) {
ri_b = db::RecursiveShapeIterator (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second);
ri_b.set_for_merged_input (true);
}
db::Region in_a (ri_a, dss, db::ICplxTrans (xor_data.layout_a->dbu () / dbu));

View File

@ -933,35 +933,6 @@ RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
new_layer ();
// try some optimization - only consider optimizing by dropping the shape-covered area under certain circumstances:
// - single layer
// - at least one shape to consider and it is a box
// - that box clips the region entirely on one side
//
// NOTE that this implementation can modify the search box on the box stack
// because we did "new_layer()" already and this function is not going to
// be called, because we do so only for single layers.
if (m_for_merged_input && (! m_has_layers || m_layers.size () == 1) && ! m_shape.at_end ()) {
box_type box = m_shape->rectangle ();
if (! box.empty ()) {
// Need to enlarge the empty area somewhat so we really exclude instances
// entirely enclosed by the shape - also the ones at the border.
if (! m_overlapping) {
box.enlarge (box_type::vector_type (1, 1));
}
const box_type &region = m_local_region_stack.back ();
unsigned int l = m_has_layers ? m_layers.front () : m_layer;
box = (cell ()->bbox (l) & region) - box;
m_local_region_stack.back () = box;
}
}
if (m_overlapping) {
m_inst = cell ()->begin_touching (m_local_region_stack.back ().enlarged (box_type::vector_type (-1, -1)));
} else {
@ -994,6 +965,33 @@ RecursiveShapeIterator::new_inst (RecursiveShapeReceiver *receiver) const
}
}
if (m_for_merged_input && (! m_has_layers || m_layers.size () == 1)) {
// Try some optimization: if the instance we're looking at is entirely covered
// by a rectangle (other objects are too expensive to check), then wil skip it
//
// We check 10 shapes max.
unsigned int l = m_has_layers ? m_layers.front () : m_layer;
box_type inst_bx = m_inst->bbox (m_box_convert);
auto si = cell ()->shapes (l).begin_overlapping (inst_bx, m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
bool skip = false;
size_t nmax = 10;
while (! skip && ! si.at_end () && nmax-- > 0) {
if (inst_bx.inside (si->rectangle ())) {
skip = true;
break;
}
++si;
}
if (skip) {
++m_inst;
continue;
}
}
bool all_of_instance = false;
bool with_region = false;

View File

@ -1683,7 +1683,7 @@ TEST(13_ForMergedPerformance)
++n;
}
tl::info << "Counted " << n << " shapes on 66/20";
EXPECT_EQ (n, size_t (1217072));
EXPECT_EQ (n, size_t (1212844));
}
{
@ -1694,7 +1694,7 @@ TEST(13_ForMergedPerformance)
++n;
}
tl::info << "Counted " << n << " shapes on 235/4";
EXPECT_EQ (n, size_t (919));
EXPECT_EQ (n, size_t (10));
}
si1.set_for_merged_input (false);
@ -1735,7 +1735,7 @@ TEST(13_ForMergedPerformance)
++n;
}
tl::info << "Counted " << n << " shapes on 66/20";
EXPECT_EQ (n, size_t (218736));
EXPECT_EQ (n, size_t (218552));
}
{
@ -1746,7 +1746,7 @@ TEST(13_ForMergedPerformance)
++n;
}
tl::info << "Counted " << n << " shapes on 235/4";
EXPECT_EQ (n, size_t (1));
EXPECT_EQ (n, size_t (2));
}
{
@ -1757,7 +1757,7 @@ TEST(13_ForMergedPerformance)
db::Region r2 (si1);
EXPECT_EQ (r1.count (), size_t (218823));
EXPECT_EQ (r2.count (), size_t (218736));
EXPECT_EQ (r2.count (), size_t (218552));
EXPECT_EQ ((r1 ^ r2).count (), size_t (0));
}
@ -1769,7 +1769,7 @@ TEST(13_ForMergedPerformance)
db::Region r2 (si2);
EXPECT_EQ (r1.count (), size_t (2578));
EXPECT_EQ (r2.count (), size_t (1));
EXPECT_EQ (r2.count (), size_t (2));
EXPECT_EQ ((r1 ^ r2).count (), size_t (0));
}
}