Skip to content

Commit

Permalink
SimplifyCFG: do constant folding also in SimplifyCFG.
Browse files Browse the repository at this point in the history
This enables to optimize chains of constant-foldable terminal instructions, for which we would have needed multiple ConstantPropagaion-SimplifyCFG pass pairs in the pipeline otherwise.
See the test file for an example.
  • Loading branch information
eeckstein committed Jan 19, 2018
1 parent 41c2991 commit 4f8cccf
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
42 changes: 34 additions & 8 deletions lib/SILOptimizer/Transforms/SimplifyCFG.cpp
Expand Up @@ -26,6 +26,7 @@
#include "swift/SILOptimizer/Utils/CFG.h"
#include "swift/SILOptimizer/Utils/CastOptimizer.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/Utils/ConstantFolding.h"
#include "swift/SILOptimizer/Utils/SILInliner.h"
#include "swift/SILOptimizer/Utils/SILSSAUpdater.h"
#include "llvm/ADT/SmallPtrSet.h"
Expand Down Expand Up @@ -75,13 +76,25 @@ namespace {
// Dominance and post-dominance info for the current function
DominanceInfo *DT = nullptr;

ConstantFolder ConstFolder;

void constFoldingCallback(SILInstruction *I) {
// If a terminal instruction gets constant folded (like cond_br), it
// enables further simplify-CFG optimizations.
if (isa<TermInst>(I))
addToWorklist(I->getParent());
}

bool ShouldVerify;
bool EnableJumpThread;
public:
SimplifyCFG(SILFunction &Fn, SILPassManager *PM, bool Verify,
bool EnableJumpThread)
: Fn(Fn), PM(PM), ShouldVerify(Verify),
EnableJumpThread(EnableJumpThread) {}
: Fn(Fn), PM(PM),
ConstFolder(PM->getOptions().AssertConfig,
/* EnableDiagnostics */false,
[&](SILInstruction *I) { constFoldingCallback(I); }),
ShouldVerify(Verify), EnableJumpThread(EnableJumpThread) {}

bool run();

Expand Down Expand Up @@ -1092,18 +1105,24 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
/// result in exposing opportunities for CFG simplification.
bool SimplifyCFG::simplifyBranchOperands(OperandValueArrayRef Operands) {
bool Simplified = false;
for (auto O = Operands.begin(), E = Operands.end(); O != E; ++O)
for (auto O = Operands.begin(), E = Operands.end(); O != E; ++O) {
// All of our interesting simplifications are on single-value instructions
// for now.
if (auto *I = dyn_cast<SingleValueInstruction>(*O))
if (SILValue Result = simplifyInstruction(I)) {
if (auto *I = dyn_cast<SingleValueInstruction>(*O)) {
SILValue Result = simplifyInstruction(I);

// The Result can be the same instruction I in case it is in an
// unreachable block. In this case it can reference itself as operand.
if (Result && Result != I) {
DEBUG(llvm::dbgs() << "simplify branch operand " << *I);
I->replaceAllUsesWith(Result);
if (isInstructionTriviallyDead(I)) {
eraseFromParentWithDebugInsts(I);
Simplified = true;
}
}
}
}
return Simplified;
}

Expand Down Expand Up @@ -1228,9 +1247,16 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
// If there are any BB arguments in the destination, replace them with the
// branch operands, since they must dominate the dest block.
for (unsigned i = 0, e = BI->getArgs().size(); i != e; ++i) {
if (DestBB->getArgument(i) != BI->getArg(i))
DestBB->getArgument(i)->replaceAllUsesWith(BI->getArg(i));
else {
if (DestBB->getArgument(i) != BI->getArg(i)) {
SILValue Val = BI->getArg(i);
DestBB->getArgument(i)->replaceAllUsesWith(Val);
if (auto *I = dyn_cast<SingleValueInstruction>(Val)) {
// Replacing operands may trigger constant folding which then could
// trigger other simplify-CFG optimizations.
ConstFolder.addToWorklist(I);
ConstFolder.processWorkList();
}
} else {
// We must be processing an unreachable part of the cfg with a cycle.
// bb1(arg1): // preds: bb3
// br bb2
Expand Down
35 changes: 35 additions & 0 deletions test/SILOptimizer/simplify_cfg.sil
Expand Up @@ -2982,3 +2982,38 @@ bb7:
br bb5
}

// CHECK-LABEL: sil @test_constant_folding
// CHECK: [[R:%[0-9]+]] = integer_literal $Builtin.Int32, 30
// CHECK: return [[R]] : $Builtin.Int32
// CHECK-NEXT: }
sil @test_constant_folding : $@convention(thin) () -> Builtin.Int32 {
bb0:
%0 = integer_literal $Builtin.Int1, 0
%20 = integer_literal $Builtin.Int32, 20
%30 = integer_literal $Builtin.Int32, 30
cond_br %0, bb1, bb2
bb1:
br bb3(%20 : $Builtin.Int32)
bb2:
br bb3(%30 : $Builtin.Int32)

bb3(%2 : $Builtin.Int32):
%3 = builtin "cmp_slt_Int32"(%2 : $Builtin.Int32, %30 : $Builtin.Int32) : $Builtin.Int1
cond_br %3, bb4, bb5
bb4:
br bb6(%20 : $Builtin.Int32)
bb5:
br bb6(%30 : $Builtin.Int32)

bb6(%4 : $Builtin.Int32):
%5 = builtin "cmp_slt_Int32"(%4 : $Builtin.Int32, %30 : $Builtin.Int32) : $Builtin.Int1
cond_br %5, bb7, bb8
bb7:
br bb9(%20 : $Builtin.Int32)
bb8:
br bb9(%30 : $Builtin.Int32)

bb9(%6 : $Builtin.Int32):
return %6 : $Builtin.Int32
}

0 comments on commit 4f8cccf

Please sign in to comment.