|
10 | 10 | // |
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
| 13 | +#include "swift/SILOptimizer/Utils/InstructionDeleter.h" |
13 | 14 | #include "swift/SIL/SILFunction.h" |
| 15 | +#include "swift/SIL/Test.h" |
14 | 16 | #include "swift/SILOptimizer/Utils/ConstExpr.h" |
15 | 17 | #include "swift/SILOptimizer/Utils/DebugOptUtils.h" |
16 | | -#include "swift/SILOptimizer/Utils/InstructionDeleter.h" |
17 | 18 | #include "swift/SILOptimizer/Utils/InstOptUtils.h" |
18 | 19 |
|
19 | 20 | using namespace swift; |
@@ -60,6 +61,21 @@ static bool isScopeAffectingInstructionDead(SILInstruction *inst, |
60 | 61 | if (!hasOnlyEndOfScopeOrEndOfLifetimeUses(inst)) { |
61 | 62 | return false; |
62 | 63 | } |
| 64 | + |
| 65 | + // If inst has any owned move-only value as a result, deleting it may shorten |
| 66 | + // that value's lifetime which is illegal according to language rules. |
| 67 | + // |
| 68 | + // In particular, this check is needed before returning true when |
| 69 | + // getSingleValueCopyOrCast returns true. That function returns true for |
| 70 | + // move_value instructions. And `move_value %moveOnlyValue` must not be |
| 71 | + // deleted. |
| 72 | + for (auto result : inst->getResults()) { |
| 73 | + if (result->getType().isPureMoveOnly() && |
| 74 | + result->getOwnershipKind() == OwnershipKind::Owned) { |
| 75 | + return false; |
| 76 | + } |
| 77 | + } |
| 78 | + |
63 | 79 | // If inst is a copy or beginning of scope, inst is dead, since we know that |
64 | 80 | // it is used only in a destroy_value or end-of-scope instruction. |
65 | 81 | if (getSingleValueCopyOrCast(inst)) |
@@ -289,6 +305,22 @@ bool InstructionDeleter::deleteIfDead(SILInstruction *inst, bool fixLifetime) { |
289 | 305 | return false; |
290 | 306 | } |
291 | 307 |
|
| 308 | +namespace swift::test { |
| 309 | +// Arguments: |
| 310 | +// - instruction: the instruction to delete |
| 311 | +// Dumps: |
| 312 | +// - the function |
| 313 | +static FunctionTest DeleterDeleteIfDeadTest( |
| 314 | + "deleter-delete-if-dead", [](auto &function, auto &arguments, auto &test) { |
| 315 | + auto *inst = arguments.takeInstruction(); |
| 316 | + InstructionDeleter deleter; |
| 317 | + llvm::dbgs() << "Deleting-if-dead " << *inst; |
| 318 | + auto deleted = deleter.deleteIfDead(inst); |
| 319 | + llvm::dbgs() << "deleteIfDead returned " << deleted << "\n"; |
| 320 | + function.dump(); |
| 321 | + }); |
| 322 | +} // namespace swift::test |
| 323 | + |
292 | 324 | void InstructionDeleter::forceDeleteAndFixLifetimes(SILInstruction *inst) { |
293 | 325 | SILFunction *fun = inst->getFunction(); |
294 | 326 | bool preserveDebugInfo = |
|
0 commit comments