Skip to content

Commit 3a4c7e9

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
Cheaper phi predecessor replacement
Summary: Instead of creating a new hashmap and rebuilding the block and value lists (Phi::setArgs()), update the lists in place when a single (block,value) pair is replaced. Reviewed By: yoney Differential Revision: D114385060 fbshipit-source-id: 76a8b8240b623285f472fd472c3098c6f790d4ff
1 parent fc119bb commit 3a4c7e9

2 files changed

Lines changed: 35 additions & 11 deletions

File tree

cinderx/Jit/hir/hir.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,38 @@ std::size_t Phi::blockIndex(const BasicBlock* block) const {
194194
return std::distance(basic_blocks_.begin(), it);
195195
}
196196

197+
void Phi::replacePredecessor(BasicBlock* old_pred, BasicBlock* new_pred) {
198+
auto it = std::lower_bound(
199+
basic_blocks_.begin(),
200+
basic_blocks_.end(),
201+
old_pred->id,
202+
[](auto block, int id) { return block->id < id; });
203+
if (it == basic_blocks_.end() || *it != old_pred) {
204+
return;
205+
}
206+
207+
std::size_t i = std::distance(basic_blocks_.begin(), it);
208+
Register* value = getOperand(i);
209+
210+
// Move the updated pair left until block IDs are sorted.
211+
while (i > 0 && new_pred->id < basic_blocks_[i - 1]->id) {
212+
basic_blocks_[i] = basic_blocks_[i - 1];
213+
operandAt(i) = getOperand(i - 1);
214+
--i;
215+
}
216+
217+
// Move the updated pair right until block IDs are sorted.
218+
while (i + 1 < basic_blocks_.size() &&
219+
basic_blocks_[i + 1]->id < new_pred->id) {
220+
basic_blocks_[i] = basic_blocks_[i + 1];
221+
operandAt(i) = getOperand(i + 1);
222+
++i;
223+
}
224+
225+
basic_blocks_[i] = new_pred;
226+
operandAt(i) = value;
227+
}
228+
197229
Edge::Edge(const Edge& other) {
198230
setFrom(other.from_);
199231
setTo(other.to_);
@@ -1145,17 +1177,7 @@ void BasicBlock::fixupPhis(BasicBlock* old_pred, BasicBlock* new_pred) {
11451177
// same block, but we already can't handle that correctly with our current Phi
11461178
// setup.
11471179

1148-
forEachPhi([&](Phi& phi) {
1149-
std::unordered_map<BasicBlock*, Register*> args;
1150-
for (size_t i = 0, n = phi.numOperands(); i < n; ++i) {
1151-
auto block = phi.basicBlocks()[i];
1152-
if (block == old_pred) {
1153-
block = new_pred;
1154-
}
1155-
args[block] = phi.getOperand(i);
1156-
}
1157-
phi.setArgs(args);
1158-
});
1180+
forEachPhi([&](Phi& phi) { phi.replacePredecessor(old_pred, new_pred); });
11591181
}
11601182

11611183
void BasicBlock::addPhiPredecessor(BasicBlock* old_pred, BasicBlock* new_pred) {

cinderx/Jit/hir/hir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,8 @@ class INSTR_CLASS(Phi, (TTop), HasOutput, Operands<>) {
11721172
// Return the index of the given predecessor in basic_blocks.
11731173
std::size_t blockIndex(const BasicBlock* block) const;
11741174

1175+
void replacePredecessor(BasicBlock* old_pred, BasicBlock* new_pred);
1176+
11751177
const std::vector<BasicBlock*> basicBlocks() const {
11761178
return basic_blocks_;
11771179
}

0 commit comments

Comments
 (0)