| 
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