From 5caacef5c1cbd8c710908b2213677311247b7d9f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 18 Jun 2015 22:22:30 +0000 Subject: [PATCH] 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 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 46 +++++++++++++------ test/CodeGen/X86/switch.ll | 34 +++++++++----- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index ed0334841df..ab988f69dc3 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -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 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 LastElement(N); // NumTables[i]: nbr of >= MinJumpTableSize partitions from Clusters[i..N-1]. SmallVector NumTables(N); - // TotalCases[i]: Total nbr of cases in Clusters[0..i]. - SmallVector 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: "; diff --git a/test/CodeGen/X86/switch.ll b/test/CodeGen/X86/switch.ll index a4dece65479..fc217d5203d 100644 --- a/test/CodeGen/X86/switch.ll +++ b/test/CodeGen/X86/switch.ll @@ -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 } -- 2.34.1