diff options
| author | Julius Ikkala <julius.ikkala@gmail.com> | 2025-06-25 20:15:08 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-25 17:15:08 +0000 |
| commit | ee51fe592747fc66bd0b5757207583198068b5bd (patch) | |
| tree | 4fb830633880fcad3cce473cd8dc094321f85477 | |
| parent | d48f050cb0209a4ba9819a094ffd1e7a7c2524ee (diff) | |
Fix Phi elimination pass sometimes leaving broken insts in release builds (#7499)
* Make phi elimination pass modify branches in-place
* Add test and fix formatting
* Avoid double removal of param insts
| -rw-r--r-- | source/slang/slang-ir-eliminate-phis.cpp | 45 | ||||
| -rw-r--r-- | tests/bugs/gh-7499.slang | 26 | ||||
| -rw-r--r-- | tests/bugs/gh-7499.slang.expected | 5 |
3 files changed, 47 insertions, 29 deletions
diff --git a/source/slang/slang-ir-eliminate-phis.cpp b/source/slang/slang-ir-eliminate-phis.cpp index 1ea1673f4..a16446319 100644 --- a/source/slang/slang-ir-eliminate-phis.cpp +++ b/source/slang/slang-ir-eliminate-phis.cpp @@ -569,6 +569,10 @@ struct PhiEliminationContext // to keep `param` around. // param->removeAndDeallocate(); + + // Avoid referencing `param` after it's been deallocated. There + // should be no uses left. + m_registerAllocation.mapInstToRegister.remove(param); } } @@ -904,20 +908,21 @@ struct PhiEliminationContext } // Once we are sure all the assignment operations have been performed, - // we can set about replacing the unconditional branch itself. + // we can set about removing the phi arguments from the unconditional + // branch itself. // - replaceBranch(branch); + updateBranch(branch); } - // Replacing the branch instruction at the end of a predecessor block + // Updating the branch instruction at the end of a predecessor block // is relatively simple, and just a bit of busy-work. // - void replaceBranch(IRUnconditionalBranch* oldBranch) + void updateBranch(IRUnconditionalBranch* branch) { // When creating a replacement instruction here, we need to make sure // that we keep all the operands that weren't phi arguments. // - Count oldOperandCount = oldBranch->getOperandCount(); + Count oldOperandCount = branch->getOperandCount(); Count paramCount = getParamCount(); Count newOperandCount = oldOperandCount - paramCount; @@ -934,32 +939,14 @@ struct PhiEliminationContext static const Count kMaxNewOperandCount = 3; SLANG_ASSERT(newOperandCount <= kMaxNewOperandCount); - ShortList<IRInst*> newOperands; - for (Index i = 0; i < newOperandCount; ++i) - { - newOperands.add(oldBranch->getOperand(i)); - } - - // Add operands for any remaining phi parameters that has not been eliminated. - for (UInt i = 0; i < (UInt)phiInfos.getCount(); i++) + // Eliminate phi parameters + for (UInt i = 0, j = 0; i < (UInt)phiInfos.getCount(); i++) { - if (!phiInfos[i].param.temp) - newOperands.add(oldBranch->getArg(i)); + if (phiInfos[i].param.temp) + branch->removeOperand(newOperandCount + j); + else + ++j; } - - auto newBranch = m_builder.emitIntrinsicInst( - oldBranch->getFullType(), - oldBranch->getOp(), - newOperands.getCount(), - newOperands.getArrayView().getBuffer()); - oldBranch->transferDecorationsTo(newBranch); - newBranch->sourceLoc = oldBranch->sourceLoc; - - // TODO: We could consider just modifying `branch` in-place by clearing - // the relevant operands for the phi arguments and setting its operand - // count to a lower value. - // - oldBranch->removeAndDeallocate(); } bool canLoadBeFoldedAtInst(IRInst* load, IRInst* useSite) diff --git a/tests/bugs/gh-7499.slang b/tests/bugs/gh-7499.slang new file mode 100644 index 000000000..ea5432758 --- /dev/null +++ b/tests/bugs/gh-7499.slang @@ -0,0 +1,26 @@ +//TEST:EXECUTABLE: +[mutating] +public void f(Ptr<int> arr, inout int size) +{ + for (int i = 0; i < 1; ++i) + arr[i] = 0; + + int end = 0; + if (end >= size) + end = size; + + for (int i = 0; i < 1; ++i) + arr[i] = 0; + + size -= end; +} + +export __extern_cpp int main() +{ + // Success is not crashing the compiler. + int size = 0; + int arr = 0; + f(&arr, size); + + return 0; +} diff --git a/tests/bugs/gh-7499.slang.expected b/tests/bugs/gh-7499.slang.expected new file mode 100644 index 000000000..4c32e2510 --- /dev/null +++ b/tests/bugs/gh-7499.slang.expected @@ -0,0 +1,5 @@ +result code = 0 +standard error = { +} +standard output = { +} |
