llvm.org GIT mirror llvm / e3c665a
Omit range checks from jump tables when lowering switches with unreachable default During the lowering of a switch that would result in the generation of a jump table, a range check is performed before indexing into the jump table, for the switch value being outside the jump table range and a conditional branch is inserted to jump to the default block. In case the default block is unreachable, this conditional jump can be omitted. This patch implements omitting this conditional branch for unreachable defaults. Review Reference: D52002 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350186 91177308-0d34-0410-b5e6-96231b3b80d8 Ayonam Ray 9 months ago
3 changed file(s) with 95 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
21882188 JumpTableReg, SwitchOp);
21892189 JT.Reg = JumpTableReg;
21902190
2191 // Emit the range check for the jump table, and branch to the default block
2192 // for the switch statement if the value being switched on exceeds the largest
2193 // case in the switch.
2194 SDValue CMP = DAG.getSetCC(
2195 dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
2196 Sub.getValueType()),
2197 Sub, DAG.getConstant(JTH.Last - JTH.First, dl, VT), ISD::SETUGT);
2198
2199 SDValue BrCond = DAG.getNode(ISD::BRCOND, dl,
2200 MVT::Other, CopyTo, CMP,
2201 DAG.getBasicBlock(JT.Default));
2202
2203 // Avoid emitting unnecessary branches to the next block.
2204 if (JT.MBB != NextBlock(SwitchBB))
2205 BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond,
2206 DAG.getBasicBlock(JT.MBB));
2207
2208 DAG.setRoot(BrCond);
2191 if (!JTH.OmitRangeCheck) {
2192 // Emit the range check for the jump table, and branch to the default block
2193 // for the switch statement if the value being switched on exceeds the
2194 // largest case in the switch.
2195 SDValue CMP = DAG.getSetCC(
2196 dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
2197 Sub.getValueType()),
2198 Sub, DAG.getConstant(JTH.Last - JTH.First, dl, VT), ISD::SETUGT);
2199
2200 SDValue BrCond = DAG.getNode(ISD::BRCOND, dl,
2201 MVT::Other, CopyTo, CMP,
2202 DAG.getBasicBlock(JT.Default));
2203
2204 // Avoid emitting unnecessary branches to the next block.
2205 if (JT.MBB != NextBlock(SwitchBB))
2206 BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond,
2207 DAG.getBasicBlock(JT.MBB));
2208
2209 DAG.setRoot(BrCond);
2210 } else {
2211 SDValue BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, CopyTo,
2212 DAG.getBasicBlock(JT.MBB));
2213 DAG.setRoot(BrCond);
2214 }
22092215 }
22102216
22112217 /// Create a LOAD_STACK_GUARD node, and let it carry the target specific global
95579563 ->createJumpTableIndex(Table);
95589564
95599565 // Set up the jump table info.
9566 bool UnreachableDefault =
9567 isa(SI->getDefaultDest()->getFirstNonPHIOrDbg());
9568 bool OmitRangeCheck = UnreachableDefault;
95609569 JumpTable JT(-1U, JTI, JumpTableMBB, nullptr);
95619570 JumpTableHeader JTH(Clusters[First].Low->getValue(),
95629571 Clusters[Last].High->getValue(), SI->getCondition(),
9563 nullptr, false);
9572 nullptr, false, OmitRangeCheck);
95649573 JTCases.emplace_back(std::move(JTH), std::move(JT));
95659574
95669575 JTCluster = CaseCluster::jumpTable(Clusters[First].Low, Clusters[Last].High,
1029710306 const SwitchInst &SI, CaseClusterVector &Clusters,
1029810307 BranchProbability &PeeledCaseProb) {
1029910308 MachineBasicBlock *SwitchMBB = FuncInfo.MBB;
10309
1030010310 // Don't perform if there is only one cluster or optimizing for size.
1030110311 if (SwitchPeelThreshold > 100 || !FuncInfo.BPI || Clusters.size() < 2 ||
1030210312 TM.getOptLevel() == CodeGenOpt::None ||
1034910359 // Extract cases from the switch.
1035010360 BranchProbabilityInfo *BPI = FuncInfo.BPI;
1035110361 CaseClusterVector Clusters;
10362
1035210363 Clusters.reserve(SI.getNumCases());
1035310364 for (auto I : SI.cases()) {
1035410365 MachineBasicBlock *Succ = FuncInfo.MBBMap[I.getCaseSuccessor()];
1036510376 // optimization levels because it's cheap to do and will make codegen faster
1036610377 // if there are many clusters.
1036710378 sortAndRangeify(Clusters);
10368
10369 if (TM.getOptLevel() != CodeGenOpt::None) {
10370 // Replace an unreachable default with the most popular destination.
10371 // FIXME: Exploit unreachable default more aggressively.
10372 bool UnreachableDefault =
10373 isa(SI.getDefaultDest()->getFirstNonPHIOrDbg());
10374 if (UnreachableDefault && !Clusters.empty()) {
10375 DenseMap Popularity;
10376 unsigned MaxPop = 0;
10377 const BasicBlock *MaxBB = nullptr;
10378 for (auto I : SI.cases()) {
10379 const BasicBlock *BB = I.getCaseSuccessor();
10380 if (++Popularity[BB] > MaxPop) {
10381 MaxPop = Popularity[BB];
10382 MaxBB = BB;
10383 }
10384 }
10385 // Set new default.
10386 assert(MaxPop > 0 && MaxBB);
10387 DefaultMBB = FuncInfo.MBBMap[MaxBB];
10388
10389 // Remove cases that were pointing to the destination that is now the
10390 // default.
10391 CaseClusterVector New;
10392 New.reserve(Clusters.size());
10393 for (CaseCluster &CC : Clusters) {
10394 if (CC.MBB != DefaultMBB)
10395 New.push_back(CC);
10396 }
10397 Clusters = std::move(New);
10398 }
10399 }
1040010379
1040110380 // The branch probablity of the peeled case.
1040210381 BranchProbability PeeledCaseProb = BranchProbability::getZero();
278278 const Value *SValue;
279279 MachineBasicBlock *HeaderBB;
280280 bool Emitted;
281 bool OmitRangeCheck;
281282
282283 JumpTableHeader(APInt F, APInt L, const Value *SV, MachineBasicBlock *H,
283 bool E = false)
284 bool E = false, bool ORC = false)
284285 : First(std::move(F)), Last(std::move(L)), SValue(SV), HeaderBB(H),
285 Emitted(E) {}
286 Emitted(E), OmitRangeCheck(ORC) {}
286287 };
287288 using JumpTableBlock = std::pair;
288289
0 ; RUN: llc -O3 -o - %s | FileCheck %s
1
2 ; Test that the output in the presence of an unreachable default does not have
3 ; a compare and branch at the top of the switch to handle the default case.
4
5 target triple = "aarch64-unknown-linux-gnu"
6
7 ; Function Attrs: nounwind
8 define void @fn(i4) {
9 switch i4 %0, label %default [
10 i4 0, label %case_0
11 i4 1, label %case_1
12 i4 2, label %case_2
13 i4 3, label %case_3
14 i4 4, label %case_4
15 i4 5, label %case_5
16 ]
17
18 ; CHECK-LABEL: fn:
19 ; CHECK-NOT: sub
20 ; CHECK-NOT: cmp
21 ; CHECK-NOT: b.hi
22 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, {{x[0-9]+}}, lsl #3]
23 ; CHECK: br {{x[0-9]+}}
24
25 default:
26 unreachable
27
28 case_0:
29 tail call void @handle_case_00(i4 %0) #2
30 br label %return_label
31
32 case_1:
33 tail call void @handle_case_01(i4 %0) #2
34 br label %return_label
35
36 case_2:
37 tail call void @handle_case_02(i4 %0) #2
38 br label %return_label
39
40 case_3:
41 tail call void @handle_case_03(i4 %0) #2
42 br label %return_label
43
44 case_4:
45 tail call void @handle_case_04(i4 %0) #2
46 br label %return_label
47
48 case_5:
49 tail call void @handle_case_05(i4 %0) #2
50 br label %return_label
51
52 return_label:
53 ret void
54 }
55
56 declare void @handle_case_00(i4)
57 declare void @handle_case_01(i4)
58 declare void @handle_case_02(i4)
59 declare void @handle_case_03(i4)
60 declare void @handle_case_04(i4)
61 declare void @handle_case_05(i4)