Skip to content

Commit b6d1aef

Browse files
committed
[SwitchLowering] Support merging 0 and power-of-2 case.
1 parent abd59ba commit b6d1aef

File tree

4 files changed

+72
-17
lines changed

4 files changed

+72
-17
lines changed

llvm/include/llvm/CodeGen/SwitchLoweringUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ enum CaseClusterKind {
3535
/// A cluster of cases suitable for jump table lowering.
3636
CC_JumpTable,
3737
/// A cluster of cases suitable for bit test lowering.
38-
CC_BitTests
38+
CC_BitTests,
39+
CC_And
3940
};
4041

4142
/// A cluster of case labels.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12238,6 +12238,32 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
1223812238

1223912239
break;
1224012240
}
12241+
case CC_And: {
12242+
SDLoc dl = getCurSDLoc();
12243+
12244+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
12245+
EVT VT = TLI.getValueType(DAG.getDataLayout(), I->Low->getType(), true);
12246+
SDValue C = DAG.getConstant(*I->Low, dl, VT);
12247+
SDValue Zero = DAG.getConstant(0, dl, VT);
12248+
SDValue CondLHS = getValue(Cond);
12249+
SDValue And = DAG.getNode(ISD::AND, dl, C.getValueType(), CondLHS, C);
12250+
auto CondD = DAG.getSetCC(dl, MVT::i1, And, Zero, ISD::SETEQ);
12251+
SDNodeFlags Flags;
12252+
SDValue BrCond =
12253+
DAG.getNode(ISD::BRCOND, dl, MVT::Other, getControlRoot(), CondD,
12254+
DAG.getBasicBlock(I->MBB), Flags);
12255+
12256+
// Insert the false branch. Do this even if it's a fall through branch,
12257+
// this makes it easier to do DAG optimizations which require inverting
12258+
// the branch condition.
12259+
BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond,
12260+
DAG.getBasicBlock(Fallthrough));
12261+
addSuccessorWithProb(CurMBB, I->MBB, UnhandledProbs);
12262+
addSuccessorWithProb(CurMBB, Fallthrough,
12263+
BranchProbability::getUnknown());
12264+
CurMBB->normalizeSuccProbs();
12265+
DAG.setRoot(BrCond);
12266+
}
1224112267
}
1224212268
CurMBB = Fallthrough;
1224312269
}

llvm/lib/CodeGen/SwitchLoweringUtils.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,39 @@ void SwitchCG::SwitchLowering::findBitTestClusters(CaseClusterVector &Clusters,
362362
}
363363
}
364364
Clusters.resize(DstIndex);
365+
366+
unsigned ZeroIdx = -1;
367+
for (const auto &[Idx, C] : enumerate(Clusters)) {
368+
if (C.Kind != CC_Range || C.Low != C.High)
369+
continue;
370+
if (C.Low->isZero()) {
371+
ZeroIdx = Idx;
372+
break;
373+
}
374+
}
375+
376+
if (ZeroIdx == -1u)
377+
return;
378+
379+
unsigned Pow2Idx = -1;
380+
for (const auto &[Idx, C] : enumerate(Clusters)) {
381+
if (C.Kind != CC_Range || C.Low != C.High || C.MBB != Clusters[ZeroIdx].MBB)
382+
continue;
383+
if (C.Low->getValue().isPowerOf2()) {
384+
Pow2Idx = Idx;
385+
break;
386+
}
387+
}
388+
389+
if (Pow2Idx == -1u)
390+
return;
391+
392+
APInt Pow2 = Clusters[Pow2Idx].Low->getValue();
393+
APInt NewC = (Pow2 + 1) * -1;
394+
Clusters[ZeroIdx].Low = ConstantInt::get(SI->getContext(), NewC);
395+
Clusters[ZeroIdx].Low = ConstantInt::get(SI->getContext(), NewC);
396+
Clusters[ZeroIdx].Kind = CC_And;
397+
Clusters.erase(Clusters.begin() + Pow2Idx);
365398
}
366399

367400
bool SwitchCG::SwitchLowering::buildBitTests(CaseClusterVector &Clusters,

llvm/test/CodeGen/AArch64/switch-cases-to-branch-and.ll

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,25 @@
44
define i32 @switch_with_matching_dests_0_and_pow2_3_cases(i8 %v) {
55
; CHECK-LABEL: switch_with_matching_dests_0_and_pow2_3_cases:
66
; CHECK: ; %bb.0: ; %entry
7-
; CHECK-NEXT: mov w9, #100 ; =0x64
8-
; CHECK-NEXT: mov w8, #20 ; =0x14
7+
; CHECK-NEXT: mov w8, #100 ; =0x64
8+
; CHECK-NEXT: mov w9, #223 ; =0xdf
99
; CHECK-NEXT: LBB0_1: ; %loop.header
1010
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
11-
; CHECK-NEXT: ands w10, w0, #0xff
12-
; CHECK-NEXT: b.eq LBB0_6
11+
; CHECK-NEXT: tst w0, w9
12+
; CHECK-NEXT: b.eq LBB0_4
1313
; CHECK-NEXT: ; %bb.2: ; %loop.header
1414
; CHECK-NEXT: ; in Loop: Header=BB0_1 Depth=1
15-
; CHECK-NEXT: cmp w10, #32
16-
; CHECK-NEXT: b.eq LBB0_6
17-
; CHECK-NEXT: ; %bb.3: ; %loop.header
18-
; CHECK-NEXT: ; in Loop: Header=BB0_1 Depth=1
15+
; CHECK-NEXT: and w10, w0, #0xff
1916
; CHECK-NEXT: cmp w10, #124
20-
; CHECK-NEXT: b.eq LBB0_7
21-
; CHECK-NEXT: ; %bb.4: ; %loop.latch
17+
; CHECK-NEXT: b.eq LBB0_5
18+
; CHECK-NEXT: ; %bb.3: ; %loop.latch
2219
; CHECK-NEXT: ; in Loop: Header=BB0_1 Depth=1
23-
; CHECK-NEXT: subs w9, w9, #1
20+
; CHECK-NEXT: subs w8, w8, #1
2421
; CHECK-NEXT: b.ne LBB0_1
25-
; CHECK-NEXT: ; %bb.5:
26-
; CHECK-NEXT: mov w8, #20 ; =0x14
27-
; CHECK-NEXT: LBB0_6: ; %common.ret
28-
; CHECK-NEXT: mov w0, w8
22+
; CHECK-NEXT: LBB0_4:
23+
; CHECK-NEXT: mov w0, #20 ; =0x14
2924
; CHECK-NEXT: ret
30-
; CHECK-NEXT: LBB0_7: ; %e2
25+
; CHECK-NEXT: LBB0_5: ; %e2
3126
; CHECK-NEXT: mov w0, #30 ; =0x1e
3227
; CHECK-NEXT: ret
3328
entry:

0 commit comments

Comments
 (0)