From fe34c28f1221c7c4d00145c18db2d49c4912e97c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 3 Nov 2013 05:24:59 +0000 Subject: [PATCH] teach silcombine to use the new InstSimplify functionality. Also switch it to use an ArrayRef in one place. Swift SVN r9898 --- lib/SILPasses/SILCombine.cpp | 59 +++++++++++++++++++++++----------- test/SILPasses/sil_combine.sil | 13 +++++++- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/lib/SILPasses/SILCombine.cpp b/lib/SILPasses/SILCombine.cpp index 36989525d4c..3042aeb0e31 100644 --- a/lib/SILPasses/SILCombine.cpp +++ b/lib/SILPasses/SILCombine.cpp @@ -29,6 +29,7 @@ #include "swift/Subsystems.h" using namespace swift; +STATISTIC(NumSimplified, "Number of instructions simplified"); STATISTIC(NumCombined, "Number of instructions combined"); STATISTIC(NumDeadInst, "Number of dead insts eliminated"); @@ -69,15 +70,17 @@ public: /// Add the given list of instructions in reverse order to the worklist. This /// routine assumes that the worklist is empty and the given list has no /// duplicates. - void addInitialGroup(SILInstruction *const *List, unsigned NumEntries) { + void addInitialGroup(ArrayRef List) { assert(Worklist.empty() && "Worklist must be empty to add initial group"); - Worklist.reserve(NumEntries+16); - WorklistMap.resize(NumEntries); - DEBUG(llvm::dbgs() << "SC: ADDING: " << NumEntries + Worklist.reserve(List.size()+16); + WorklistMap.resize(List.size()); + DEBUG(llvm::dbgs() << "SC: ADDING: " << List.size() << " instrs to worklist\n"); - for (unsigned Idx = 0; NumEntries; --NumEntries) { - SILInstruction *I = List[NumEntries-1]; - WorklistMap.insert(std::make_pair(I, Idx++)); + while (!List.empty()) { + SILInstruction *I = List.back(); + List = List.slice(0, List.size()-1); + + WorklistMap.insert(std::make_pair(I, Worklist.size())); Worklist.push_back(I); } } @@ -88,7 +91,7 @@ public: if (It == WorklistMap.end()) return; // Not in worklist. // Don't bother moving everything down, just null out the slot. We will - // check before we process any instruction if it is 0. + // check before we process any instruction if it is null. Worklist[It->second] = 0; WorklistMap.erase(It); @@ -104,8 +107,8 @@ public: /// When an instruction has been simplified, add all of its users to the /// worklist since additional simplifications of its users may have been /// exposed. - void addUsersToWorklist(SILInstruction &I) { - for (auto UI : I.getUses()) + void addUsersToWorklist(ValueBase *I) { + for (auto UI : I->getUses()) add(UI->getUser()); } @@ -175,7 +178,7 @@ public: // to the worklist, replace all uses of I with the new value, then return I, // so that the combiner will know that I was modified. SILInstruction *replaceInstUsesWith(SILInstruction &I, ValueBase *V) { - Worklist.addUsersToWorklist(I); // Add all modified instrs to worklist. + Worklist.addUsersToWorklist(&I); // Add all modified instrs to worklist. DEBUG(llvm::dbgs() << "SC: Replacing " << I << "\n" " with " << *V << '\n'); @@ -207,8 +210,8 @@ public: return 0; // Don't do anything with I } - void addInitialGroup(SILInstruction *const *List, unsigned NumEntries) { - Worklist.addInitialGroup(List, NumEntries); + void addInitialGroup(ArrayRef List) { + Worklist.addInitialGroup(List); } /// Base visitor that does not do anything. @@ -281,8 +284,7 @@ static void addReachableCodeToWorklist(SILBasicBlock *BB, SILCombiner &SC) { // function down. This jives well with the way that it adds all uses of // instructions to the worklist after doing a transformation, thus avoiding // some N^2 behavior in pathological cases. - SC.addInitialGroup(&InstrsForSILCombineWorklist[0], - InstrsForSILCombineWorklist.size()); + SC.addInitialGroup(InstrsForSILCombineWorklist); } bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { @@ -299,7 +301,7 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { SILInstruction *I = Worklist.removeOne(); // When we erase an instruction, we use the map in the worklist to check if - // the instruction is in the worklist. If it is, we replace it with 0 + // the instruction is in the worklist. If it is, we replace it with null // instead of shifting all members of the worklist towards the front. This // check makes sure that if we run into any such residual null pointers, we // skip them. @@ -318,6 +320,25 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { // Now that we have an instruction, try simplifying it. Builder->setInsertionPoint(I->getParent(), I); + // Check to see if we can instsimplify the instruction. + if (SILValue Result = simplifyInstruction(I)) { + ++NumSimplified; + + DEBUG(llvm::dbgs() << "SC: Simplify Old = " << *I << '\n' + << " New = " << *Result.getDef() << '\n'); + + // Everything uses the new instruction now. + replaceInstUsesWith(*I, Result.getDef()); + + // Push the new instruction and any users onto the worklist. + Worklist.addUsersToWorklist(Result.getDef()); + + eraseInstFromFunction(*I); + MadeChange = true; + continue; + } + + #ifndef NDEBUG std::string OrigI; #endif @@ -336,9 +357,9 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { // Push the new instruction and any users onto the worklist. Worklist.add(Result); - Worklist.addUsersToWorklist(*Result); + Worklist.addUsersToWorklist(Result); - // Insert the new instruction into the basic block... + // Insert the new instruction into the basic block. SILBasicBlock *InstParent = I->getParent(); SILBasicBlock::iterator InsertPos = I; @@ -355,7 +376,7 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { eraseInstFromFunction(*I); } else { Worklist.add(I); - Worklist.addUsersToWorklist(*I); + Worklist.addUsersToWorklist(I); } } MadeChange = true; diff --git a/test/SILPasses/sil_combine.sil b/test/SILPasses/sil_combine.sil index 8309b1acbfa..f5a17f15ce3 100644 --- a/test/SILPasses/sil_combine.sil +++ b/test/SILPasses/sil_combine.sil @@ -3,6 +3,7 @@ import Builtin import swift + ////////////////////// // Simple DCE Tests // ////////////////////// @@ -132,7 +133,7 @@ bb0(%0 : $B): // CHECK-NOT: object_pointer_to_ref // CHECK: } sil @removeTriviallyDeadCrossBasicBlocks : $@thin (b : B, m : Builtin.Int1) -> () { -bb0(%0: $B, %1: $Builtin.Int1): +bb0(%0: $B, %1: $Builtin.Int1): %5 = ref_to_object_pointer %0 : $B to $Builtin.ObjectPointer %13 = cond_br %1, bb1, bb2 bb1: @@ -158,3 +159,13 @@ bb0: %3 = tuple () return %3 : $() } + +// CHECK-LABEL: sil @tuple_extract +// CHECK: bb +// CHECK-NEXT: return %0 +sil @tuple_extract : $@thin (a : Int64) -> Int64 { +bb0(%0 : $Int64): + %1 = tuple (%0 : $Int64, %0 : $Int64) + %2 = tuple_extract %1 : $(Int64, Int64), 0 + return %2 : $Int64 +}