llvm.org GIT mirror llvm / f7bb38c
[SimplifyCFG] try harder to forward switch condition to phi (PR34471) The missed canonicalization/optimization in the motivating test from PR34471 leads to very different codegen: int switcher(int x) { switch(x) { case 17: return 17; case 19: return 19; case 42: return 42; default: break; } return 0; } int comparator(int x) { if (x == 17) return 17; if (x == 19) return 19; if (x == 42) return 42; return 0; } For the first example, we use a bit-test optimization to avoid a series of compare-and-branch: https://godbolt.org/g/BivDsw Differential Revision: https://reviews.llvm.org/D39011 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316293 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 2 years ago
2 changed file(s) with 35 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
44494449 static bool ForwardSwitchConditionToPHI(SwitchInst *SI) {
44504450 typedef DenseMap> ForwardingNodesMap;
44514451 ForwardingNodesMap ForwardingNodes;
4452
4452 BasicBlock *SwitchBlock = SI->getParent();
4453 bool Changed = false;
44534454 for (auto &Case : SI->cases()) {
44544455 ConstantInt *CaseValue = Case.getCaseValue();
44554456 BasicBlock *CaseDest = Case.getCaseSuccessor();
4457
4458 // Replace phi operands in successor blocks that are using the constant case
4459 // value rather than the switch condition variable:
4460 // switchbb:
4461 // switch i32 %x, label %default [
4462 // i32 17, label %succ
4463 // ...
4464 // succ:
4465 // %r = phi i32 ... [ 17, %switchbb ] ...
4466 // -->
4467 // %r = phi i32 ... [ %x, %switchbb ] ...
4468
4469 for (Instruction &InstInCaseDest : *CaseDest) {
4470 auto *Phi = dyn_cast(&InstInCaseDest);
4471 if (!Phi) break;
4472
4473 // This only works if there is exactly 1 incoming edge from the switch to
4474 // a phi. If there is >1, that means multiple cases of the switch map to 1
4475 // value in the phi, and that phi value is not the switch condition. Thus,
4476 // this transform would not make sense (the phi would be invalid because
4477 // a phi can't have different incoming values from the same block).
4478 int SwitchBBIdx = Phi->getBasicBlockIndex(SwitchBlock);
4479 if (Phi->getIncomingValue(SwitchBBIdx) == CaseValue &&
4480 count(Phi->blocks(), SwitchBlock) == 1) {
4481 Phi->setIncomingValue(SwitchBBIdx, SI->getCondition());
4482 Changed = true;
4483 }
4484 }
4485
4486 // Collect phi nodes that are indirectly using this switch's case constants.
44564487 int PhiIdx;
44574488 if (auto *Phi = FindPHIForConditionForwarding(CaseValue, CaseDest, &PhiIdx))
44584489 ForwardingNodes[Phi].push_back(PhiIdx);
44594490 }
44604491
4461 bool Changed = false;
44624492 for (auto &ForwardingNode : ForwardingNodes) {
44634493 PHINode *Phi = ForwardingNode.first;
44644494 SmallVectorImpl &Indexes = ForwardingNode.second;
4949 ; CHECK-NEXT: entry:
5050 ; CHECK-NEXT: switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
5151 ; CHECK-NEXT: i32 17, label [[RETURN:%.*]]
52 ; CHECK-NEXT: i32 19, label [[IF19:%.*]]
53 ; CHECK-NEXT: i32 42, label [[IF42:%.*]]
52 ; CHECK-NEXT: i32 19, label [[RETURN]]
53 ; CHECK-NEXT: i32 42, label [[RETURN]]
5454 ; CHECK-NEXT: ]
55 ; CHECK: if19:
56 ; CHECK-NEXT: br label [[RETURN]]
57 ; CHECK: if42:
58 ; CHECK-NEXT: br label [[RETURN]]
5955 ; CHECK: else3:
6056 ; CHECK-NEXT: br label [[RETURN]]
6157 ; CHECK: return:
62 ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[X]], [[IF19]] ], [ [[X]], [[IF42]] ], [ 0, [[ELSE3]] ], [ 17, [[ENTRY:%.*]] ]
58 ; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ELSE3]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[X]], [[ENTRY]] ], [ [[X]], [[ENTRY]] ]
6359 ; CHECK-NEXT: ret i32 [[R]]
6460 ;
6561 entry: