Switch lowering: enable whole-switch jump tables at -O0.

To same compile time, the analysis to find dense case-clusters in switches is
not done at -O0. However, when the whole switch is dense enough, it is easy to
turn it into a jump table, resulting in much faster code with no extra effort.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240071 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hans Wennborg 2015-06-18 22:22:30 +00:00
parent 50cef0052f
commit 5caacef5c1
2 changed files with 53 additions and 27 deletions

View File

@ -7504,6 +7504,31 @@ void SelectionDAGBuilder::findJumpTables(CaseClusterVector &Clusters,
const int64_t N = Clusters.size();
const unsigned MinJumpTableSize = TLI.getMinimumJumpTableEntries();
// TotalCases[i]: Total nbr of cases in Clusters[0..i].
SmallVector<unsigned, 8> TotalCases(N);
for (unsigned i = 0; i < N; ++i) {
APInt Hi = Clusters[i].High->getValue();
APInt Lo = Clusters[i].Low->getValue();
TotalCases[i] = (Hi - Lo).getLimitedValue() + 1;
if (i != 0)
TotalCases[i] += TotalCases[i - 1];
}
if (N >= MinJumpTableSize && isDense(Clusters, &TotalCases[0], 0, N - 1)) {
// Cheap case: the whole range might be suitable for jump table.
CaseCluster JTCluster;
if (buildJumpTable(Clusters, 0, N - 1, SI, DefaultMBB, JTCluster)) {
Clusters[0] = JTCluster;
Clusters.resize(1);
return;
}
}
// The algorithm below is not suitable for -O0.
if (TM.getOptLevel() == CodeGenOpt::None)
return;
// Split Clusters into minimum number of dense partitions. The algorithm uses
// the same idea as Kannan & Proebsting "Correction to 'Producing Good Code
// for the Case Statement'" (1994), but builds the MinPartitions array in
@ -7517,16 +7542,6 @@ void SelectionDAGBuilder::findJumpTables(CaseClusterVector &Clusters,
SmallVector<unsigned, 8> LastElement(N);
// NumTables[i]: nbr of >= MinJumpTableSize partitions from Clusters[i..N-1].
SmallVector<unsigned, 8> NumTables(N);
// TotalCases[i]: Total nbr of cases in Clusters[0..i].
SmallVector<unsigned, 8> TotalCases(N);
for (unsigned i = 0; i < N; ++i) {
APInt Hi = Clusters[i].High->getValue();
APInt Lo = Clusters[i].Low->getValue();
TotalCases[i] = (Hi - Lo).getLimitedValue() + 1;
if (i != 0)
TotalCases[i] += TotalCases[i - 1];
}
// Base case: There is only one way to partition Clusters[N-1].
MinPartitions[N - 1] = 1;
@ -7714,6 +7729,10 @@ void SelectionDAGBuilder::findBitTestClusters(CaseClusterVector &Clusters,
assert(Clusters[i-1].High->getValue().slt(Clusters[i].Low->getValue()));
#endif
// The algorithm below is not suitable for -O0.
if (TM.getOptLevel() == CodeGenOpt::None)
return;
// If target does not have legal shift left, do not emit bit tests at all.
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
EVT PTy = TLI.getPointerTy();
@ -8129,11 +8148,8 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
return;
}
if (TM.getOptLevel() != CodeGenOpt::None) {
findJumpTables(Clusters, &SI, DefaultMBB);
findBitTestClusters(Clusters, &SI);
}
findJumpTables(Clusters, &SI, DefaultMBB);
findBitTestClusters(Clusters, &SI);
DEBUG({
dbgs() << "Case clusters: ";

View File

@ -16,23 +16,18 @@ bb1: tail call void @g(i32 1) br label %return
bb2: tail call void @g(i32 1) br label %return
return: ret void
; Should be lowered as straight compares in -O0 mode.
; NOOPT-LABEL: basic
; NOOPT: subl $1, %eax
; NOOPT: je
; NOOPT: subl $3, %eax
; NOOPT: je
; NOOPT: subl $4, %eax
; NOOPT: je
; NOOPT: subl $5, %eax
; NOOPT: je
; Jump table otherwise.
; Lowered as a jump table, both with and without optimization.
; CHECK-LABEL: basic
; CHECK: decl
; CHECK: cmpl $4
; CHECK: ja
; CHECK: jmpq *.LJTI
; NOOPT-LABEL: basic
; NOOPT: decl
; NOOPT: subl $4
; NOOPT: ja
; NOOPT: movq .LJTI
; NOOPT: jmpq
}
@ -205,6 +200,21 @@ return: ret void
; CHECK: leal -5
; CHECK: cmpl $10
; CHECK: jmpq *.LJTI
; At -O0, we don't build jump tables for only parts of a switch.
; NOOPT-LABEL: optimal_jump_table1
; NOOPT: testl %edi, %edi
; NOOPT: je
; NOOPT: subl $5, %eax
; NOOPT: je
; NOOPT: subl $6, %eax
; NOOPT: je
; NOOPT: subl $12, %eax
; NOOPT: je
; NOOPT: subl $13, %eax
; NOOPT: je
; NOOPT: subl $15, %eax
; NOOPT: je
}