aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stubbs <ams@codesourcery.com>2020-02-26 16:45:29 +0000
committerAndrew Stubbs <ams@codesourcery.com>2020-02-27 12:03:10 +0000
commit82863a5cc99143f93203b2caed3750c7313a87ea (patch)
tree525147e716ce241f5f9234052bba2afd287e7ba3
parenteb8e6a30a442c4c12dc903d6e1817b223bbed4a3 (diff)
downloadgcc-82863a5cc99143f93203b2caed3750c7313a87ea.zip
gcc-82863a5cc99143f93203b2caed3750c7313a87ea.tar.gz
gcc-82863a5cc99143f93203b2caed3750c7313a87ea.tar.bz2
amdgcn: fix ICE on subreg of BI reg.
BImode usually only requires one bit, but instructions that write to VCC also clobber the reset of the DImode register pair, so gcn_class_max_nregs reports that two registers are needed for BImode. Paradoxically, accessing VCC via SImode is therefore uses fewer registers than accessing via BImode. The LRA checking code takes this into account, but the DF liveness data also looks at the subreg, so it says (subreg:SI (reg:BI VCC) 0) only makes the low part live. Both are "correct", but they disagree, which causes an ICE. This doesn't happen when writing conditions to VCC; it happens when accessing VCC_LO via a regular move to a regular SImode register. If we transform the subregs so that BImode is always the outer mode then it basically means the same thing, except that now both LRA and DF calculate nregs the same, and ICE goes away. As soon as LRA is done the subregs all evaporate anyway. 2020-02-27 Andrew Stubbs <ams@codesourcery.com> gcc/ * config/gcn/gcn.md (mov<mode>): Add transformations for BI subregs.
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/gcn/gcn.md25
2 files changed, 29 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index beb56bc..b17d255 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2020-02-27 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn.md (mov<mode>): Add transformations for BI subregs.
+
2020-02-27 Mark Williams <mwilliams@fb.com>
* dwarf2out.c (file_name_acquire): Call remap_debug_filename.
diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index b527d9a..d8b49df 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -395,6 +395,31 @@
(match_operand:MOV_MODE 1 "general_operand"))]
""
{
+ if (SUBREG_P (operands[1])
+ && GET_MODE (operands[1]) == SImode
+ && GET_MODE (SUBREG_REG (operands[1])) == BImode)
+ {
+ /* (reg:BI VCC) has nregs==2 to ensure it gets clobbered as a whole,
+ but (subreg:SI (reg:BI VCC)) doesn't, which causes the LRA liveness
+ checks to assert. Transform this:
+ (set (reg:SI) (subreg:SI (reg:BI)))
+ to this:
+ (set (subreg:BI (reg:SI)) (reg:BI)) */
+ operands[0] = gen_rtx_SUBREG (BImode, operands[0], 0);
+ operands[1] = SUBREG_REG (operands[1]);
+ }
+ if (SUBREG_P (operands[0])
+ && GET_MODE (operands[0]) == SImode
+ && GET_MODE (SUBREG_REG (operands[0])) == BImode)
+ {
+ /* Likewise, transform this:
+ (set (subreg:SI (reg:BI)) (reg:SI))
+ to this:
+ (set (reg:BI) (subreg:BI (reg:SI))) */
+ operands[0] = SUBREG_REG (operands[0]);
+ operands[1] = gen_rtx_SUBREG (BImode, operands[1], 0);
+ }
+
if (MEM_P (operands[0]))
operands[1] = force_reg (<MODE>mode, operands[1]);