fn add_site(&mut self, mut new: Site, counter: i32) -> Option<i32> {
        // If any of the existing sites do not contain the new one already...
        if !self.sites.iter().any(|s| s.contains(&new)) {
            // keep only the sites that the new site does not contain, and add the new site.
            // TODO can replace with drain_filter when its stabilized.
            let mut first_seen = i32::max_value();
            let mut i = 0;
            while i != self.sites.len() {
                if new.contains(&self.sites[i]) {
                    let previous_site = self.sites.swap_remove(i);
                    first_seen = ::std::cmp::min(previous_site.first_seen, first_seen);
                } else {
                    i += 1;
                }
            }

            if first_seen == i32::max_value() {
                // The input counter is the first time we're seeing this site.
                first_seen = counter;
            }

            new.first_seen = first_seen;
            self.sites.push(new);
            Some(first_seen)
        } else {
            None
        }
    }
Adds a new site if that site or a ancestor of it does not exist.

Returns the first counter value recorded for this site if the site was added, or `None` if
the site was not added.

In order to enable backtracking for symbols that need to be redefined at a higher site,
this method also takes the current counter value of the CSE, and tracks the counter value
for the first time the site was added. When the symbol is redefined, the counter
should be reset to this value so the site list and `generate_bindings` will maintain
consistent counter values.

`new` will not be added if an ancestor already exists. Conversely, if children of `new`
exist in the list, they will be removed when `new` is added.
weld/src/optimizer/transforms/cse.rs