mirror of https://github.com/KLayout/klayout.git
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:
parent
5699c91d3f
commit
cb5a1f7d3e
|
|
@ -680,13 +680,17 @@ bool run_tiled_xor (const XORData &xor_data)
|
||||||
if (ll->second.first < 0) {
|
if (ll->second.first < 0) {
|
||||||
proc.input (in_a, db::RecursiveShapeIterator ());
|
proc.input (in_a, db::RecursiveShapeIterator ());
|
||||||
} else {
|
} 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) {
|
if (ll->second.second < 0) {
|
||||||
proc.input (in_b, db::RecursiveShapeIterator ());
|
proc.input (in_b, db::RecursiveShapeIterator ());
|
||||||
} else {
|
} 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 + "; ";
|
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) {
|
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 = 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) {
|
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 = 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));
|
db::Region in_a (ri_a, dss, db::ICplxTrans (xor_data.layout_a->dbu () / dbu));
|
||||||
|
|
|
||||||
|
|
@ -933,35 +933,6 @@ RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
|
||||||
|
|
||||||
new_layer ();
|
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) {
|
if (m_overlapping) {
|
||||||
m_inst = cell ()->begin_touching (m_local_region_stack.back ().enlarged (box_type::vector_type (-1, -1)));
|
m_inst = cell ()->begin_touching (m_local_region_stack.back ().enlarged (box_type::vector_type (-1, -1)));
|
||||||
} else {
|
} 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 all_of_instance = false;
|
||||||
bool with_region = false;
|
bool with_region = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1683,7 +1683,7 @@ TEST(13_ForMergedPerformance)
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
tl::info << "Counted " << n << " shapes on 66/20";
|
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;
|
++n;
|
||||||
}
|
}
|
||||||
tl::info << "Counted " << n << " shapes on 235/4";
|
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);
|
si1.set_for_merged_input (false);
|
||||||
|
|
@ -1735,7 +1735,7 @@ TEST(13_ForMergedPerformance)
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
tl::info << "Counted " << n << " shapes on 66/20";
|
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;
|
++n;
|
||||||
}
|
}
|
||||||
tl::info << "Counted " << n << " shapes on 235/4";
|
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);
|
db::Region r2 (si1);
|
||||||
|
|
||||||
EXPECT_EQ (r1.count (), size_t (218823));
|
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));
|
EXPECT_EQ ((r1 ^ r2).count (), size_t (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1769,7 +1769,7 @@ TEST(13_ForMergedPerformance)
|
||||||
db::Region r2 (si2);
|
db::Region r2 (si2);
|
||||||
|
|
||||||
EXPECT_EQ (r1.count (), size_t (2578));
|
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));
|
EXPECT_EQ ((r1 ^ r2).count (), size_t (0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue