diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index 9bd72e860..de1f265e4 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -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)); diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index c918068ff..b86f5d010 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -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 ®ion = 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; diff --git a/src/db/unit_tests/dbRecursiveShapeIteratorTests.cc b/src/db/unit_tests/dbRecursiveShapeIteratorTests.cc index 4dda034db..0e4a7430a 100644 --- a/src/db/unit_tests/dbRecursiveShapeIteratorTests.cc +++ b/src/db/unit_tests/dbRecursiveShapeIteratorTests.cc @@ -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)); } }