@@ -5521,26 +5521,50 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
5521
5521
}
5522
5522
}
5523
5523
5524
- /* Return true if X must be a base rather than an index. */
5524
+ /* Return true if CODE applies some kind of scale. The scaled value is
5525
+ is the first operand and the scale is the second. */
5525
5526
5526
5527
static bool
5527
- must_be_base_p ( rtx x )
5528
+ binary_scale_code_p ( enum rtx_code code )
5528
5529
{
5529
- return GET_CODE (x ) == LO_SUM ;
5530
+ return (code == MULT
5531
+ || code == ASHIFT
5532
+ /* Needed by ARM targets. */
5533
+ || code == ASHIFTRT
5534
+ || code == LSHIFTRT
5535
+ || code == ROTATE
5536
+ || code == ROTATERT );
5530
5537
}
5531
5538
5532
- /* Return true if X must be an index rather than a base. */
5539
+ /* If *INNER can be interpreted as a base, return a pointer to the inner term
5540
+ (see address_info). Return null otherwise. */
5533
5541
5534
- static bool
5535
- must_be_index_p (rtx x )
5542
+ static rtx *
5543
+ get_base_term (rtx * inner )
5536
5544
{
5537
- return (GET_CODE (x ) == MULT
5538
- || GET_CODE (x ) == ASHIFT
5539
- /* Needed by ARM targets. */
5540
- || GET_CODE (x ) == ASHIFTRT
5541
- || GET_CODE (x ) == LSHIFTRT
5542
- || GET_CODE (x ) == ROTATE
5543
- || GET_CODE (x ) == ROTATERT );
5545
+ if (GET_CODE (* inner ) == LO_SUM )
5546
+ inner = strip_address_mutations (& XEXP (* inner , 0 ));
5547
+ if (REG_P (* inner )
5548
+ || MEM_P (* inner )
5549
+ || GET_CODE (* inner ) == SUBREG )
5550
+ return inner ;
5551
+ return 0 ;
5552
+ }
5553
+
5554
+ /* If *INNER can be interpreted as an index, return a pointer to the inner term
5555
+ (see address_info). Return null otherwise. */
5556
+
5557
+ static rtx *
5558
+ get_index_term (rtx * inner )
5559
+ {
5560
+ /* At present, only constant scales are allowed. */
5561
+ if (binary_scale_code_p (GET_CODE (* inner )) && CONSTANT_P (XEXP (* inner , 1 )))
5562
+ inner = strip_address_mutations (& XEXP (* inner , 0 ));
5563
+ if (REG_P (* inner )
5564
+ || MEM_P (* inner )
5565
+ || GET_CODE (* inner ) == SUBREG )
5566
+ return inner ;
5567
+ return 0 ;
5544
5568
}
5545
5569
5546
5570
/* Set the segment part of address INFO to LOC, given that INNER is the
@@ -5549,8 +5573,6 @@ must_be_index_p (rtx x)
5549
5573
static void
5550
5574
set_address_segment (struct address_info * info , rtx * loc , rtx * inner )
5551
5575
{
5552
- gcc_checking_assert (GET_CODE (* inner ) == UNSPEC );
5553
-
5554
5576
gcc_assert (!info -> segment );
5555
5577
info -> segment = loc ;
5556
5578
info -> segment_term = inner ;
@@ -5562,12 +5584,6 @@ set_address_segment (struct address_info *info, rtx *loc, rtx *inner)
5562
5584
static void
5563
5585
set_address_base (struct address_info * info , rtx * loc , rtx * inner )
5564
5586
{
5565
- if (must_be_base_p (* inner ))
5566
- inner = strip_address_mutations (& XEXP (* inner , 0 ));
5567
- gcc_checking_assert (REG_P (* inner )
5568
- || MEM_P (* inner )
5569
- || GET_CODE (* inner ) == SUBREG );
5570
-
5571
5587
gcc_assert (!info -> base );
5572
5588
info -> base = loc ;
5573
5589
info -> base_term = inner ;
@@ -5579,12 +5595,6 @@ set_address_base (struct address_info *info, rtx *loc, rtx *inner)
5579
5595
static void
5580
5596
set_address_index (struct address_info * info , rtx * loc , rtx * inner )
5581
5597
{
5582
- if (must_be_index_p (* inner ) && CONSTANT_P (XEXP (* inner , 1 )))
5583
- inner = strip_address_mutations (& XEXP (* inner , 0 ));
5584
- gcc_checking_assert (REG_P (* inner )
5585
- || MEM_P (* inner )
5586
- || GET_CODE (* inner ) == SUBREG );
5587
-
5588
5598
gcc_assert (!info -> index );
5589
5599
info -> index = loc ;
5590
5600
info -> index_term = inner ;
@@ -5596,8 +5606,6 @@ set_address_index (struct address_info *info, rtx *loc, rtx *inner)
5596
5606
static void
5597
5607
set_address_disp (struct address_info * info , rtx * loc , rtx * inner )
5598
5608
{
5599
- gcc_checking_assert (CONSTANT_P (* inner ));
5600
-
5601
5609
gcc_assert (!info -> disp );
5602
5610
info -> disp = loc ;
5603
5611
info -> disp_term = inner ;
@@ -5677,12 +5685,6 @@ static int
5677
5685
baseness (rtx x , enum machine_mode mode , addr_space_t as ,
5678
5686
enum rtx_code outer_code , enum rtx_code index_code )
5679
5687
{
5680
- /* See whether we can be certain. */
5681
- if (must_be_base_p (x ))
5682
- return 3 ;
5683
- if (must_be_index_p (x ))
5684
- return -3 ;
5685
-
5686
5688
/* Believe *_POINTER unless the address shape requires otherwise. */
5687
5689
if (REG_P (x ) && REG_POINTER (x ))
5688
5690
return 2 ;
@@ -5717,8 +5719,8 @@ decompose_normal_address (struct address_info *info)
5717
5719
if (n_ops > 1 )
5718
5720
info -> base_outer_code = PLUS ;
5719
5721
5720
- /* Separate the parts that contain a REG or MEM from those that don't.
5721
- Record the latter in INFO and leave the former in OPS. */
5722
+ /* Try to classify each sum operand now. Leave those that could be
5723
+ either a base or an index in OPS. */
5722
5724
rtx * inner_ops [4 ];
5723
5725
size_t out = 0 ;
5724
5726
for (size_t in = 0 ; in < n_ops ; ++ in )
@@ -5731,18 +5733,31 @@ decompose_normal_address (struct address_info *info)
5731
5733
set_address_segment (info , loc , inner );
5732
5734
else
5733
5735
{
5734
- ops [out ] = loc ;
5735
- inner_ops [out ] = inner ;
5736
- ++ out ;
5736
+ /* The only other possibilities are a base or an index. */
5737
+ rtx * base_term = get_base_term (inner );
5738
+ rtx * index_term = get_index_term (inner );
5739
+ gcc_assert (base_term || index_term );
5740
+ if (!base_term )
5741
+ set_address_index (info , loc , index_term );
5742
+ else if (!index_term )
5743
+ set_address_base (info , loc , base_term );
5744
+ else
5745
+ {
5746
+ gcc_assert (base_term == index_term );
5747
+ ops [out ] = loc ;
5748
+ inner_ops [out ] = base_term ;
5749
+ ++ out ;
5750
+ }
5737
5751
}
5738
5752
}
5739
5753
5740
5754
/* Classify the remaining OPS members as bases and indexes. */
5741
5755
if (out == 1 )
5742
5756
{
5743
- /* Assume that the remaining value is a base unless the shape
5744
- requires otherwise. */
5745
- if (!must_be_index_p (* inner_ops [0 ]))
5757
+ /* If we haven't seen a base or an index yet, assume that this is
5758
+ the base. If we were confident that another term was the base
5759
+ or index, treat the remaining operand as the other kind. */
5760
+ if (!info -> base )
5746
5761
set_address_base (info , ops [0 ], inner_ops [0 ]);
5747
5762
else
5748
5763
set_address_index (info , ops [0 ], inner_ops [0 ]);
0 commit comments