- String binary search does 1 less string comparison
- Identifier linear scan on large attribute list is switched to string binary search
Details
- Reviewers
rriddle - Commits
- rG2125eb3446d3: [mlir][core] Slightly improved attribute lookup
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 305–311 | I was going to add it to DictionaryAttr but since that's tied up in ODS I didn't bother... | |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 260–264 | ||
| 271–273 | Is the bool return important? What is the performance if you just return end() if the name isn't found? | |
| 274–275 | Just use ptrdiff_t. | |
| 280 | Spell out auto here. | |
| 295 | Drop the 16, it could change. Prefer being somewhat ambiguous on exact numbers of heuristics in comments. | |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 271–273 | For a linear search, the only gain is that you skip one extra it == end() check. For a binary search, it's important to know whether the attribute was actually found, because, if not, then it will be the sorted insertion point. If just end() was returned:
| |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 271–273 | And if the attribute was actually found (with a StringRef lookup) then it->first == name will compare the entire string (think operand_segment_sizes...) | |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 271–273 | Why would the binary search be different? Wouldn't we just return end in all of the cases where you currently return false, and the current iterator whenever you return true? | |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 271–273 | Case 1: attribute is found. Returning just an iterator: c++ auto it = findAttrSorted(begin(), end(), name); return it == end() ? Attribute() : it->second; // vs auto it = findAttrSorted(begin(), end(), name); return it.second ? it.first->second : Attribute(); All that happens is that the == end() check is skipped, which isn't much, but: Case 2: setting an attribute c++
auto it = findAttrSorted(begin(), end(), name);
// a: attribute is found
if (it != end()) {
it->second = value;
return;
}
// b: attribute is not found, where should the attribute be inserted?
it = llvm::lower_bound(begin(), end(), name); // re-search the list
attrs.insert(it, {name, value});
// vs
auto it = findAttrSorted(begin(), end(), name);
if (it.second) {
it.first->second = value;
return;
}
// it.first will be the sorted insertion point
attrs.insert(it.first, {name, value});
// vs lower_bound
auto it = llvm::lower_bound(begin(), end(), name);
if (it != end() && it->first == name) { // re-compare the whole string (if found)
it->second = value;
return;
}
attrs.insert(it, {name, value});Essentially, the bool contains the result of it->first == name so that it doesn't have to be re-checked. | |
| mlir/include/mlir/IR/OperationSupport.h | ||
|---|---|---|
| 271–273 | Right, I missed where this was being used for insertion. | |
| mlir/lib/IR/OperationSupport.cpp | ||
|---|---|---|
| 122–128 | Since this one is set(Identifier, Attribute), the identifier lookup doesn't return the sorted insertion point (either end() or the found attribute). You can either:
I chose (2) because that was the previous behaviour of the function. | |