@@ -2442,10 +2442,31 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value)
2442
2442
class SwitchInst : public TerminatorInst {
2443
2443
void *operator new (size_t , unsigned ); // DO NOT IMPLEMENT
2444
2444
unsigned ReservedSpace;
2445
+ // Operands format:
2445
2446
// Operand[0] = Value to switch on
2446
2447
// Operand[1] = Default basic block destination
2447
2448
// Operand[2n ] = Value to match
2448
2449
// Operand[2n+1] = BasicBlock to go to on match
2450
+
2451
+ // Store case values separately from operands list. We needn't User-Use
2452
+ // concept here, since it is just a case value, it will always constant,
2453
+ // and case value couldn't reused with another instructions/values.
2454
+ // Additionally:
2455
+ // It allows us to use custom type for case values that is not inherited
2456
+ // from Value. Since case value is a complex type that implements
2457
+ // the subset of integers, we needn't extract sub-constants within
2458
+ // slow getAggregateElement method.
2459
+ // For case values we will use std::list to by two reasons:
2460
+ // 1. It allows to add/remove cases without whole collection reallocation.
2461
+ // 2. In most of cases we needn't random access.
2462
+ // Currently case values are also stored in Operands List, but it will moved
2463
+ // out in future commits.
2464
+ typedef std::list<IntegersSubset> Subsets;
2465
+ typedef Subsets::iterator SubsetsIt;
2466
+ typedef Subsets::const_iterator SubsetsConstIt;
2467
+
2468
+ Subsets TheSubsets;
2469
+
2449
2470
SwitchInst (const SwitchInst &SI);
2450
2471
void init (Value *Value, BasicBlock *Default, unsigned NumReserved);
2451
2472
void growOperands ();
@@ -2470,12 +2491,20 @@ class SwitchInst : public TerminatorInst {
2470
2491
virtual SwitchInst *clone_impl () const ;
2471
2492
public:
2472
2493
2473
- template <class SwitchInstTy , class ConstantIntTy , class BasicBlockTy >
2494
+ // FIXME: Currently there are a lot of unclean template parameters,
2495
+ // we need to make refactoring in future.
2496
+ // All these parameters are used to implement both iterator and const_iterator
2497
+ // without code duplication.
2498
+ // SwitchInstTy may be "const SwitchInst" or "SwitchInst"
2499
+ // ConstantIntTy may be "const ConstantInt" or "ConstantInt"
2500
+ // SubsetsItTy may be SubsetsConstIt or SubsetsIt
2501
+ // BasicBlockTy may be "const BasicBlock" or "BasicBlock"
2502
+ template <class SwitchInstTy , class ConstantIntTy ,
2503
+ class SubsetsItTy , class BasicBlockTy >
2474
2504
class CaseIteratorT ;
2475
2505
2476
- typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock>
2477
- ConstCaseIt;
2478
-
2506
+ typedef CaseIteratorT<const SwitchInst, const ConstantInt,
2507
+ SubsetsConstIt, const BasicBlock> ConstCaseIt;
2479
2508
class CaseIt ;
2480
2509
2481
2510
// -2
@@ -2516,34 +2545,34 @@ class SwitchInst : public TerminatorInst {
2516
2545
// / Returns a read/write iterator that points to the first
2517
2546
// / case in SwitchInst.
2518
2547
CaseIt case_begin () {
2519
- return CaseIt (this , 0 );
2548
+ return CaseIt (this , 0 , TheSubsets. begin () );
2520
2549
}
2521
2550
// / Returns a read-only iterator that points to the first
2522
2551
// / case in the SwitchInst.
2523
2552
ConstCaseIt case_begin () const {
2524
- return ConstCaseIt (this , 0 );
2553
+ return ConstCaseIt (this , 0 , TheSubsets. begin () );
2525
2554
}
2526
2555
2527
2556
// / Returns a read/write iterator that points one past the last
2528
2557
// / in the SwitchInst.
2529
2558
CaseIt case_end () {
2530
- return CaseIt (this , getNumCases ());
2559
+ return CaseIt (this , getNumCases (), TheSubsets. end () );
2531
2560
}
2532
2561
// / Returns a read-only iterator that points one past the last
2533
2562
// / in the SwitchInst.
2534
2563
ConstCaseIt case_end () const {
2535
- return ConstCaseIt (this , getNumCases ());
2564
+ return ConstCaseIt (this , getNumCases (), TheSubsets. end () );
2536
2565
}
2537
2566
// / Returns an iterator that points to the default case.
2538
2567
// / Note: this iterator allows to resolve successor only. Attempt
2539
2568
// / to resolve case value causes an assertion.
2540
2569
// / Also note, that increment and decrement also causes an assertion and
2541
2570
// / makes iterator invalid.
2542
2571
CaseIt case_default () {
2543
- return CaseIt (this , DefaultPseudoIndex);
2572
+ return CaseIt (this , DefaultPseudoIndex, TheSubsets. end () );
2544
2573
}
2545
2574
ConstCaseIt case_default () const {
2546
- return ConstCaseIt (this , DefaultPseudoIndex);
2575
+ return ConstCaseIt (this , DefaultPseudoIndex, TheSubsets. end () );
2547
2576
}
2548
2577
2549
2578
// / findCaseValue - Search all of the case values for the specified constant.
@@ -2597,7 +2626,7 @@ class SwitchInst : public TerminatorInst {
2597
2626
// / Note:
2598
2627
// / This action invalidates iterators for all cases following the one removed,
2599
2628
// / including the case_end() iterator.
2600
- void removeCase (CaseIt i);
2629
+ void removeCase (CaseIt& i);
2601
2630
2602
2631
unsigned getNumSuccessors () const { return getNumOperands ()/2 ; }
2603
2632
BasicBlock *getSuccessor (unsigned idx) const {
@@ -2622,24 +2651,38 @@ class SwitchInst : public TerminatorInst {
2622
2651
2623
2652
// Case iterators definition.
2624
2653
2625
- template <class SwitchInstTy , class ConstantIntTy , class BasicBlockTy >
2654
+ template <class SwitchInstTy , class ConstantIntTy ,
2655
+ class SubsetsItTy , class BasicBlockTy >
2626
2656
class CaseIteratorT {
2627
2657
protected:
2628
2658
2629
2659
SwitchInstTy *SI;
2630
- unsigned Index;
2631
-
2632
- public:
2633
-
2634
- typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, BasicBlockTy> Self;
2660
+ unsigned long Index;
2661
+ SubsetsItTy SubsetIt;
2635
2662
2636
2663
// / Initializes case iterator for given SwitchInst and for given
2637
2664
// / case number.
2638
- CaseIteratorT (SwitchInstTy *SI, unsigned CaseNum) {
2665
+ friend class SwitchInst ;
2666
+ CaseIteratorT (SwitchInstTy *SI, unsigned SuccessorIndex,
2667
+ SubsetsItTy CaseValueIt) {
2639
2668
this ->SI = SI;
2640
- Index = CaseNum;
2669
+ Index = SuccessorIndex;
2670
+ this ->SubsetIt = CaseValueIt;
2641
2671
}
2642
2672
2673
+ public:
2674
+ typedef typename SubsetsItTy::reference IntegersSubsetRef;
2675
+ typedef CaseIteratorT<SwitchInstTy, ConstantIntTy,
2676
+ SubsetsItTy, BasicBlockTy> Self;
2677
+
2678
+ CaseIteratorT (SwitchInstTy *SI, unsigned CaseNum) {
2679
+ this ->SI = SI;
2680
+ Index = CaseNum;
2681
+ SubsetIt = SI->TheSubsets .begin ();
2682
+ std::advance (SubsetIt, CaseNum);
2683
+ }
2684
+
2685
+
2643
2686
// / Initializes case iterator for given SwitchInst and for given
2644
2687
// / TerminatorInst's successor index.
2645
2688
static Self fromSuccessorIndex (SwitchInstTy *SI, unsigned SuccessorIndex) {
@@ -2654,19 +2697,18 @@ class SwitchInst : public TerminatorInst {
2654
2697
// / @Deprecated
2655
2698
ConstantIntTy *getCaseValue () {
2656
2699
assert (Index < SI->getNumCases () && " Index out the number of cases." );
2657
- IntegersSubset CaseRanges =
2658
- reinterpret_cast <Constant*>(SI->getOperand (2 + Index*2 ));
2659
- IntegersSubset::Range R = CaseRanges.getItem (0 );
2700
+ IntegersSubsetRef CaseRanges = *SubsetIt;
2660
2701
2661
2702
// FIXME: Currently we work with ConstantInt based cases.
2662
2703
// So return CaseValue as ConstantInt.
2663
- return R. getLow ( ).toConstantInt ();
2704
+ return CaseRanges. getSingleNumber ( 0 ).toConstantInt ();
2664
2705
}
2665
2706
2666
2707
// / Resolves case value for current case.
2708
+ // IntegersSubsetRef getCaseValueEx() {
2667
2709
IntegersSubset getCaseValueEx () {
2668
2710
assert (Index < SI->getNumCases () && " Index out the number of cases." );
2669
- return reinterpret_cast <Constant*>(SI-> getOperand ( 2 + Index* 2 )) ;
2711
+ return *SubsetIt ;
2670
2712
}
2671
2713
2672
2714
// / Resolves successor for current case.
@@ -2689,9 +2731,14 @@ class SwitchInst : public TerminatorInst {
2689
2731
2690
2732
Self operator ++() {
2691
2733
// Check index correctness after increment.
2692
- // Note: Index == getNumCases() means end().
2693
- assert (Index+1 <= SI->getNumCases () && " Index out the number of cases." );
2734
+ // Note: Index == getNumCases() means end().
2735
+ unsigned NumCases = SI->getNumCases ();
2736
+ assert (Index+1 <= NumCases && " Index out the number of cases." );
2694
2737
++Index;
2738
+ if (Index == 0 )
2739
+ SubsetIt = SI->TheSubsets .begin ();
2740
+ else
2741
+ ++SubsetIt;
2695
2742
return *this ;
2696
2743
}
2697
2744
Self operator ++(int ) {
@@ -2703,9 +2750,18 @@ class SwitchInst : public TerminatorInst {
2703
2750
// Check index correctness after decrement.
2704
2751
// Note: Index == getNumCases() means end().
2705
2752
// Also allow "-1" iterator here. That will became valid after ++.
2706
- assert ((Index == 0 || Index-1 <= SI->getNumCases ()) &&
2753
+ unsigned NumCases = SI->getNumCases ();
2754
+ assert ((Index == 0 || Index-1 <= NumCases) &&
2707
2755
" Index out the number of cases." );
2708
2756
--Index;
2757
+ if (Index == NumCases) {
2758
+ SubsetIt = SI->TheSubsets .end ();
2759
+ return *this ;
2760
+ }
2761
+
2762
+ if (Index != -1UL )
2763
+ --SubsetIt;
2764
+
2709
2765
return *this ;
2710
2766
}
2711
2767
Self operator --(int ) {
@@ -2723,14 +2779,25 @@ class SwitchInst : public TerminatorInst {
2723
2779
}
2724
2780
};
2725
2781
2726
- class CaseIt : public CaseIteratorT <SwitchInst, ConstantInt, BasicBlock> {
2782
+ class CaseIt : public CaseIteratorT <SwitchInst, ConstantInt,
2783
+ SubsetsIt, BasicBlock> {
2784
+ typedef CaseIteratorT<SwitchInst, ConstantInt, SubsetsIt, BasicBlock>
2785
+ ParentTy;
2786
+
2787
+ protected:
2788
+ friend class SwitchInst ;
2789
+ CaseIt (SwitchInst *SI, unsigned CaseNum, SubsetsIt SubsetIt) :
2790
+ ParentTy (SI, CaseNum, SubsetIt) {}
2727
2791
2728
- typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy;
2792
+ void updateCaseValueOperand (IntegersSubset& V) {
2793
+ SI->setOperand (2 + Index*2 , reinterpret_cast <Value*>((Constant*)V));
2794
+ }
2729
2795
2730
2796
public:
2797
+
2798
+ CaseIt (SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {}
2731
2799
2732
2800
CaseIt (const ParentTy& Src) : ParentTy(Src) {}
2733
- CaseIt (SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {}
2734
2801
2735
2802
// / Sets the new value for current case.
2736
2803
// / @Deprecated.
@@ -2740,14 +2807,15 @@ class SwitchInst : public TerminatorInst {
2740
2807
// FIXME: Currently we work with ConstantInt based cases.
2741
2808
// So inititalize IntItem container directly from ConstantInt.
2742
2809
Mapping.add (IntItem::fromConstantInt (V));
2743
- SI-> setOperand ( 2 + Index* 2 ,
2744
- reinterpret_cast <Value*>((Constant*)Mapping. getCase ()) );
2810
+ *SubsetIt = Mapping. getCase ();
2811
+ updateCaseValueOperand (*SubsetIt );
2745
2812
}
2746
2813
2747
2814
// / Sets the new value for current case.
2748
2815
void setValueEx (IntegersSubset& V) {
2749
2816
assert (Index < SI->getNumCases () && " Index out the number of cases." );
2750
- SI->setOperand (2 + Index*2 , reinterpret_cast <Value*>((Constant*)V));
2817
+ *SubsetIt = V;
2818
+ updateCaseValueOperand (*SubsetIt);
2751
2819
}
2752
2820
2753
2821
// / Sets the new successor for current case.
0 commit comments