[CodeGen] Replace -max-jump-table-size with -max-jump-table-targets

Modern processors predict the targets of an indirect branch regardless of
the size of any jump table used to glean its target address.  Moreover,
branch predictors typically use resources limited by the number of actual
targets that occur at run time.

This patch changes the semantics of the option `-max-jump-table-size` to limit
the number of different targets instead of the number of entries in a jump
table.  Thus, it is now renamed to `-max-jump-table-targets`.

Before, when `-max-jump-table-size` was specified, it could happen that
cluster jump tables could have targets used repeatedly, but each one was
counted and typically resulted in tables with the same number of entries.
With this patch, when specifying `-max-jump-table-targets`, tables may have
different lengths, since the number of unique targets is counted towards the
limit, but the number of unique targets in tables is the same, but for the
last one containing the balance of targets.

Differential revision: https://reviews.llvm.org/D60295

llvm-svn: 372893
This commit is contained in:
Evandro Menezes 2019-09-25 16:10:20 +00:00
parent 6b3749f696
commit 3bd8ba156b
9 changed files with 105 additions and 108 deletions

View File

@ -373,7 +373,7 @@ public:
(MaxCaseVal - MinCaseVal) (MaxCaseVal - MinCaseVal)
.getLimitedValue(std::numeric_limits<uint64_t>::max() - 1) + 1; .getLimitedValue(std::numeric_limits<uint64_t>::max() - 1) + 1;
// Check whether a range of clusters is dense enough for a jump table // Check whether a range of clusters is dense enough for a jump table
if (TLI->isSuitableForJumpTable(&SI, N, Range)) { if (TLI->isSuitableForJumpTable(&SI, N, 0, Range)) {
JumpTableSize = Range; JumpTableSize = Range;
return 1; return 1;
} }

View File

@ -221,14 +221,6 @@ struct BitTestBlock {
Cases(std::move(C)), Prob(Pr) {} Cases(std::move(C)), Prob(Pr) {}
}; };
/// Return the range of values within a range.
uint64_t getJumpTableRange(const CaseClusterVector &Clusters, unsigned First,
unsigned Last);
/// Return the number of cases within a range.
uint64_t getJumpTableNumCases(const SmallVectorImpl<unsigned> &TotalCases,
unsigned First, unsigned Last);
struct SwitchWorkListItem { struct SwitchWorkListItem {
MachineBasicBlock *MBB; MachineBasicBlock *MBB;
CaseClusterIt FirstCluster; CaseClusterIt FirstCluster;

View File

@ -1022,8 +1022,10 @@ public:
} }
/// Return true if lowering to a jump table is suitable for a set of case /// Return true if lowering to a jump table is suitable for a set of case
/// clusters which may contain \p NumCases cases, \p Range range of values. /// clusters which may contain \p NumCases cases, \p Range range of values,
virtual bool isSuitableForJumpTable(const SwitchInst *SI, uint64_t NumCases, /// \p NumTargets targets.
virtual bool isSuitableForJumpTable(const SwitchInst *SI,
uint64_t NumCases, uint64_t NumTargets,
uint64_t Range) const { uint64_t Range) const {
// FIXME: This function check the maximum table size and density, but the // FIXME: This function check the maximum table size and density, but the
// minimum size is not checked. It would be nice if the minimum size is // minimum size is not checked. It would be nice if the minimum size is
@ -1032,14 +1034,14 @@ public:
// getEstimatedNumberOfCaseClusters() in BasicTTIImpl. // getEstimatedNumberOfCaseClusters() in BasicTTIImpl.
const bool OptForSize = SI->getParent()->getParent()->hasOptSize(); const bool OptForSize = SI->getParent()->getParent()->hasOptSize();
const unsigned MinDensity = getMinimumJumpTableDensity(OptForSize); const unsigned MinDensity = getMinimumJumpTableDensity(OptForSize);
const unsigned MaxJumpTableSize = getMaximumJumpTableSize(); const unsigned MaxJumpTableTargets = getMaximumJumpTableTargets();
// Check whether the number of cases is small enough and // Check whether the number of targets is small enough and
// the range is dense enough for a jump table. // the range is dense enough for a jump table.
if ((OptForSize || Range <= MaxJumpTableSize) && if ((OptForSize || NumTargets <= MaxJumpTableTargets) &&
(NumCases * 100 >= Range * MinDensity)) { NumCases * 100 >= Range * MinDensity)
return true; return true;
}
return false; return false;
} }
@ -1542,9 +1544,8 @@ public:
/// Return lower limit of the density in a jump table. /// Return lower limit of the density in a jump table.
unsigned getMinimumJumpTableDensity(bool OptForSize) const; unsigned getMinimumJumpTableDensity(bool OptForSize) const;
/// Return upper limit for number of entries in a jump table. /// Return upper limit for number of targets in a jump table.
/// Zero if no limit. unsigned getMaximumJumpTableTargets() const;
unsigned getMaximumJumpTableSize() const;
virtual bool isJumpTableRelative() const { virtual bool isJumpTableRelative() const {
return TM.isPositionIndependent(); return TM.isPositionIndependent();
@ -1951,9 +1952,8 @@ protected:
/// Indicate the minimum number of blocks to generate jump tables. /// Indicate the minimum number of blocks to generate jump tables.
void setMinimumJumpTableEntries(unsigned Val); void setMinimumJumpTableEntries(unsigned Val);
/// Indicate the maximum number of entries in jump tables. /// Indicate the maximum number of targets in jump tables.
/// Set to zero to generate unlimited jump tables. void setMaximumJumpTableTargets(unsigned);
void setMaximumJumpTableSize(unsigned);
/// If set to a physical register, this specifies the register that /// If set to a physical register, this specifies the register that
/// llvm.savestack/llvm.restorestack should save and restore. /// llvm.savestack/llvm.restorestack should save and restore.

View File

@ -11,33 +11,47 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/SwitchLoweringUtils.h" #include "llvm/CodeGen/SwitchLoweringUtils.h"
using namespace llvm; using namespace llvm;
using namespace SwitchCG; using namespace SwitchCG;
uint64_t SwitchCG::getJumpTableRange(const CaseClusterVector &Clusters, // Collection of partition stats, made up of, for a given cluster,
unsigned First, unsigned Last) { // the range of the cases, their number and the number of unique targets.
assert(Last >= First); struct PartitionStats {
const APInt &LowCase = Clusters[First].Low->getValue(); uint64_t Range, Cases, Targets;
const APInt &HighCase = Clusters[Last].High->getValue(); };
assert(LowCase.getBitWidth() == HighCase.getBitWidth());
// FIXME: A range of consecutive cases has 100% density, but only requires one static PartitionStats getJumpTableStats(const CaseClusterVector &Clusters,
// comparison to lower. We should discriminate against such consecutive ranges unsigned First, unsigned Last,
// in jump tables. bool HasReachableDefault) {
return (HighCase - LowCase).getLimitedValue((UINT64_MAX - 1) / 100) + 1; assert(Last >= First && "Invalid order of clusters");
}
uint64_t SmallSet<const MachineBasicBlock *, 8> Targets;
SwitchCG::getJumpTableNumCases(const SmallVectorImpl<unsigned> &TotalCases, PartitionStats Stats;
unsigned First, unsigned Last) {
assert(Last >= First); Stats.Cases = 0;
assert(TotalCases[Last] >= TotalCases[First]); for (unsigned i = First; i <= Last; ++i) {
uint64_t NumCases = const APInt &Hi = Clusters[i].High->getValue(),
TotalCases[Last] - (First == 0 ? 0 : TotalCases[First - 1]); &Lo = Clusters[i].Low->getValue();
return NumCases; Stats.Cases += (Hi - Lo).getLimitedValue() + 1;
Targets.insert(Clusters[i].MBB);
}
assert(Stats.Cases < UINT64_MAX / 100 && "Too many cases");
const APInt &Hi = Clusters[Last].High->getValue(),
&Lo = Clusters[First].Low->getValue();
assert(Hi.getBitWidth() == Lo.getBitWidth());
Stats.Range = (Hi - Lo).getLimitedValue((UINT64_MAX - 1) / 100) + 1;
assert(Stats.Range >= Stats.Cases && "Invalid range or number of cases");
Stats.Targets =
Targets.size() + (HasReachableDefault && Stats.Range > Stats.Cases);
return Stats;
} }
void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters, void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters,
@ -64,23 +78,13 @@ void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters,
if (N < 2 || N < MinJumpTableEntries) if (N < 2 || N < MinJumpTableEntries)
return; return;
// Accumulated number of cases in each cluster and those prior to it. const bool HasReachableDefault =
SmallVector<unsigned, 8> TotalCases(N); !isa<UnreachableInst>(DefaultMBB->getBasicBlock()->getFirstNonPHIOrDbg());
for (unsigned i = 0; i < N; ++i) { PartitionStats Stats =
const APInt &Hi = Clusters[i].High->getValue(); getJumpTableStats(Clusters, 0, N - 1, HasReachableDefault);
const APInt &Lo = Clusters[i].Low->getValue();
TotalCases[i] = (Hi - Lo).getLimitedValue() + 1;
if (i != 0)
TotalCases[i] += TotalCases[i - 1];
}
uint64_t Range = getJumpTableRange(Clusters,0, N - 1);
uint64_t NumCases = getJumpTableNumCases(TotalCases, 0, N - 1);
assert(NumCases < UINT64_MAX / 100);
assert(Range >= NumCases);
// Cheap case: the whole range may be suitable for jump table. // Cheap case: the whole range may be suitable for jump table.
if (TLI->isSuitableForJumpTable(SI, NumCases, Range)) { if (TLI->isSuitableForJumpTable(SI, Stats.Cases, Stats.Targets, Stats.Range)) {
CaseCluster JTCluster; CaseCluster JTCluster;
if (buildJumpTable(Clusters, 0, N - 1, SI, DefaultMBB, JTCluster)) { if (buildJumpTable(Clusters, 0, N - 1, SI, DefaultMBB, JTCluster)) {
Clusters[0] = JTCluster; Clusters[0] = JTCluster;
@ -104,9 +108,6 @@ void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters,
SmallVector<unsigned, 8> MinPartitions(N); SmallVector<unsigned, 8> MinPartitions(N);
// LastElement[i] is the last element of the partition starting at i. // LastElement[i] is the last element of the partition starting at i.
SmallVector<unsigned, 8> LastElement(N); SmallVector<unsigned, 8> LastElement(N);
// PartitionsScore[i] is used to break ties when choosing between two
// partitionings resulting in the same number of partitions.
SmallVector<unsigned, 8> PartitionsScore(N);
// For PartitionsScore, a small number of comparisons is considered as good as // For PartitionsScore, a small number of comparisons is considered as good as
// a jump table and a single comparison is considered better than a jump // a jump table and a single comparison is considered better than a jump
// table. // table.
@ -116,6 +117,11 @@ void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters,
FewCases = 1, FewCases = 1,
SingleCase = 2 SingleCase = 2
}; };
// PartitionsScore[i] is used to break ties when choosing between two
// partitionings resulting in the same number of partitions.
SmallVector<unsigned, 8> PartitionsScore(N);
// PartitionsStats[j] is the stats for the partition Clusters[i..j].
SmallVector<PartitionStats, 8> PartitionsStats(N);
// Base case: There is only one way to partition Clusters[N-1]. // Base case: There is only one way to partition Clusters[N-1].
MinPartitions[N - 1] = 1; MinPartitions[N - 1] = 1;
@ -129,16 +135,16 @@ void SwitchCG::SwitchLowering::findJumpTables(CaseClusterVector &Clusters,
MinPartitions[i] = MinPartitions[i + 1] + 1; MinPartitions[i] = MinPartitions[i + 1] + 1;
LastElement[i] = i; LastElement[i] = i;
PartitionsScore[i] = PartitionsScore[i + 1] + PartitionScores::SingleCase; PartitionsScore[i] = PartitionsScore[i + 1] + PartitionScores::SingleCase;
for (int64_t j = i + 1; j < N; j++)
PartitionsStats[j] =
getJumpTableStats(Clusters, i, j, HasReachableDefault);
// Search for a solution that results in fewer partitions. // Search for a solution that results in fewer partitions.
for (int64_t j = N - 1; j > i; j--) { for (int64_t j = N - 1; j > i; j--) {
// Try building a partition from Clusters[i..j]. // Try building a partition from Clusters[i..j].
Range = getJumpTableRange(Clusters, i, j); if (TLI->isSuitableForJumpTable(SI, PartitionsStats[j].Cases,
NumCases = getJumpTableNumCases(TotalCases, i, j); PartitionsStats[j].Targets,
assert(NumCases < UINT64_MAX / 100); PartitionsStats[j].Range)) {
assert(Range >= NumCases);
if (TLI->isSuitableForJumpTable(SI, NumCases, Range)) {
unsigned NumPartitions = 1 + (j == N - 1 ? 0 : MinPartitions[j + 1]); unsigned NumPartitions = 1 + (j == N - 1 ? 0 : MinPartitions[j + 1]);
unsigned Score = j == N - 1 ? 0 : PartitionsScore[j + 1]; unsigned Score = j == N - 1 ? 0 : PartitionsScore[j + 1];
int64_t NumEntries = j - i + 1; int64_t NumEntries = j - i + 1;

View File

@ -72,9 +72,9 @@ static cl::opt<unsigned> MinimumJumpTableEntries
("min-jump-table-entries", cl::init(4), cl::Hidden, ("min-jump-table-entries", cl::init(4), cl::Hidden,
cl::desc("Set minimum number of entries to use a jump table.")); cl::desc("Set minimum number of entries to use a jump table."));
static cl::opt<unsigned> MaximumJumpTableSize static cl::opt<unsigned> MaximumJumpTableTargets
("max-jump-table-size", cl::init(UINT_MAX), cl::Hidden, ("max-jump-table-targets", cl::init(UINT_MAX), cl::Hidden,
cl::desc("Set maximum size of jump tables.")); cl::desc("Set maximum number of targets to use in a jump table."));
/// Minimum jump table density for normal functions. /// Minimum jump table density for normal functions.
static cl::opt<unsigned> static cl::opt<unsigned>
@ -1778,18 +1778,18 @@ void TargetLoweringBase::setMinimumJumpTableEntries(unsigned Val) {
MinimumJumpTableEntries = Val; MinimumJumpTableEntries = Val;
} }
unsigned TargetLoweringBase::getMaximumJumpTableTargets() const {
return MaximumJumpTableTargets;
}
void TargetLoweringBase::setMaximumJumpTableTargets(unsigned Val) {
MaximumJumpTableTargets = Val;
}
unsigned TargetLoweringBase::getMinimumJumpTableDensity(bool OptForSize) const { unsigned TargetLoweringBase::getMinimumJumpTableDensity(bool OptForSize) const {
return OptForSize ? OptsizeJumpTableDensity : JumpTableDensity; return OptForSize ? OptsizeJumpTableDensity : JumpTableDensity;
} }
unsigned TargetLoweringBase::getMaximumJumpTableSize() const {
return MaximumJumpTableSize;
}
void TargetLoweringBase::setMaximumJumpTableSize(unsigned Val) {
MaximumJumpTableSize = Val;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Reciprocal Estimates // Reciprocal Estimates
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -647,11 +647,10 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setPrefFunctionAlignment( setPrefFunctionAlignment(
llvm::Align(1ULL << STI.getPrefFunctionLogAlignment())); llvm::Align(1ULL << STI.getPrefFunctionLogAlignment()));
// Only change the limit for entries in a jump table if specified by // Only change the limit for targets in a jump table if specified by
// the sub target, but not at the command line. // the sub target, but not at the command line.
unsigned MaxJT = STI.getMaximumJumpTableSize(); if (getMaximumJumpTableTargets() == UINT_MAX)
if (MaxJT && getMaximumJumpTableSize() == UINT_MAX) setMaximumJumpTableTargets(STI.getMaximumJumpTableTargets());
setMaximumJumpTableSize(MaxJT);
setHasExtractBitsInsn(true); setHasExtractBitsInsn(true);

View File

@ -96,13 +96,13 @@ void AArch64Subtarget::initializeProperties() {
break; break;
case ExynosM1: case ExynosM1:
MaxInterleaveFactor = 4; MaxInterleaveFactor = 4;
MaxJumpTableSize = 8; MaxJumpTableTargets = 8;
PrefFunctionLogAlignment = 4; PrefFunctionLogAlignment = 4;
PrefLoopLogAlignment = 3; PrefLoopLogAlignment = 3;
break; break;
case ExynosM3: case ExynosM3:
MaxInterleaveFactor = 4; MaxInterleaveFactor = 4;
MaxJumpTableSize = 20; MaxJumpTableTargets = 20;
PrefFunctionLogAlignment = 5; PrefFunctionLogAlignment = 5;
PrefLoopLogAlignment = 4; PrefLoopLogAlignment = 4;
break; break;

View File

@ -200,7 +200,7 @@ protected:
unsigned MaxPrefetchIterationsAhead = UINT_MAX; unsigned MaxPrefetchIterationsAhead = UINT_MAX;
unsigned PrefFunctionLogAlignment = 0; unsigned PrefFunctionLogAlignment = 0;
unsigned PrefLoopLogAlignment = 0; unsigned PrefLoopLogAlignment = 0;
unsigned MaxJumpTableSize = 0; unsigned MaxJumpTableTargets = UINT_MAX;
unsigned WideningBaseCost = 0; unsigned WideningBaseCost = 0;
// ReserveXRegister[i] - X#i is not available as a general purpose register. // ReserveXRegister[i] - X#i is not available as a general purpose register.
@ -364,7 +364,7 @@ public:
} }
unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; } unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
unsigned getMaximumJumpTableSize() const { return MaxJumpTableSize; } unsigned getMaximumJumpTableTargets() const { return MaxJumpTableTargets; }
unsigned getWideningBaseCost() const { return WideningBaseCost; } unsigned getWideningBaseCost() const { return WideningBaseCost; }

View File

@ -1,9 +1,9 @@
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK0 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK0 < %t
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-size=4 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK4 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-targets=4 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK4 < %t
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-size=8 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK8 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-targets=8 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK8 < %t
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-size=16 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK16 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -max-jump-table-targets=16 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECK16 < %t
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -mcpu=exynos-m1 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECKM1 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -mcpu=exynos-m1 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECKM1 < %t
; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -mcpu=exynos-m3 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECKM3 < %t ; RUN: llc %s -O2 -print-machineinstrs -mtriple=aarch64-linux-gnu -jump-table-density=40 -mcpu=exynos-m3 -o /dev/null 2> %t; FileCheck %s --check-prefixes=CHECK,CHECKM3 < %t
declare void @ext(i32, i32) declare void @ext(i32, i32)
@ -86,11 +86,11 @@ entry:
; CHECK0-NOT: %jump-table.1: ; CHECK0-NOT: %jump-table.1:
; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4{{$}} ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4{{$}}
; CHECK4-NOT: %jump-table.1: ; CHECK4-NOT: %jump-table.1:
; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4{{$}} ; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}}
; CHECK8-NOT: %jump-table.1: ; CHECK8-NOT: %jump-table.1:
; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}} ; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}}
; CHECK16-NOT: %jump-table.1: ; CHECK16-NOT: %jump-table.1:
; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4{{$}} ; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}}
; CHECKM1-NOT: %jump-table.1: ; CHECKM1-NOT: %jump-table.1:
; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}} ; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}}
; CHECKM3-NOT: %jump-table.1: ; CHECKM3-NOT: %jump-table.1:
@ -102,6 +102,7 @@ bb3: tail call void @ext(i32 4, i32 3) br label %return
bb4: tail call void @ext(i32 3, i32 4) br label %return bb4: tail call void @ext(i32 3, i32 4) br label %return
bb5: tail call void @ext(i32 2, i32 5) br label %return bb5: tail call void @ext(i32 2, i32 5) br label %return
bb6: tail call void @ext(i32 1, i32 6) br label %return bb6: tail call void @ext(i32 1, i32 6) br label %return
return: ret void return: ret void
} }
@ -131,14 +132,13 @@ entry:
; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4
; CHECK4-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 ; CHECK4-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8
; CHECK4-NOT: %jump-table.2: ; CHECK4-NOT: %jump-table.2:
; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7
; CHECK8-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 ; CHECK8-NEXT: %jump-table.1: %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECK8-NOT: %jump-table.2: ; CHECK8-NOT: %jump-table.2:
; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 ; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECK16-NEXT: %jump-table.1: %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12 ; CHECK16-NOT: %jump-table.1:
; CHECK16-NOT: %jump-table.2: ; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7
; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECKM1-NEXT: %jump-table.1: %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECKM1-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10
; CHECKM1-NOT: %jump-table.2: ; CHECKM1-NOT: %jump-table.2:
; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 ; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10
; CHECKM3-NOT: %jump-table.1: ; CHECKM3-NOT: %jump-table.1:
@ -185,15 +185,15 @@ entry:
; CHECK0-NOT: %jump-table.1: ; CHECK0-NOT: %jump-table.1:
; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4
; CHECK4-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 ; CHECK4-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8
; CHECK4-NOT: %jump-table.2: ; CHECK4-NEXT: %jump-table.2: %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECK4-NOT: %jump-table.3:
; CHECK8-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 ; CHECK8-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8
; CHECK8-NEXT: %jump-table.1: %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECK8-NOT: %jump-table.2: ; CHECK8-NOT: %jump-table.2:
; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 ; CHECK16-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECK16-NEXT: %jump-table.1: %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12 ; CHECK16-NOT: %jump-table.1:
; CHECK16-NOT: %jump-table.2: ; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8
; CHECKM1-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 ; CHECKM1-NEXT: %jump-table.1: %bb.9 %bb.10 %bb.13 %bb.11 %bb.12
; CHECKM1-NEXT: %jump-table.1: %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10
; CHECKM1-NOT: %jump-table.2: ; CHECKM1-NOT: %jump-table.2:
; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 ; CHECKM3-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10
; CHECKM3-NOT: %jump-table.1: ; CHECKM3-NOT: %jump-table.1: