diff options
author | Kyrylo Tkachov <kyrylo.tkachov@arm.com> | 2017-11-08 18:29:38 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2017-11-08 18:29:38 +0000 |
commit | 040939a2387eff082f1594fac35f007f93d2dcd8 (patch) | |
tree | 01ecc67421aa14ffdb9721f699664279b29b4320 /gcc | |
parent | 40757a25d45d47ddc50819bfd32dd6aac595abc2 (diff) | |
download | gcc-040939a2387eff082f1594fac35f007f93d2dcd8.zip gcc-040939a2387eff082f1594fac35f007f93d2dcd8.tar.gz gcc-040939a2387eff082f1594fac35f007f93d2dcd8.tar.bz2 |
[simplify-rtx] Simplify vec_merge of vec_duplicates into vec_concat
Another vec_merge simplification that's missing from simplify-rtx.c is transforming
a vec_merge of two vec_duplicates. For example:
(set (reg:V2DF 80)
(vec_merge:V2DF (vec_duplicate:V2DF (reg:DF 84))
(vec_duplicate:V2DF (reg:DF 81))
(const_int 2)))
Can be transformed into the simpler:
(set (reg:V2DF 80)
(vec_concat:V2DF (reg:DF 81)
(reg:DF 84)))
I believe this should always be beneficial.
I'm still looking into finding a small testcase demonstrating this, but on aarch64 SPEC
I've seen this eliminate some really bizzare codegen where GCC was generating nonsense like:
ldr q18, [sp, 448]
ins v18.d[0], v23.d[0]
ins v18.d[1], v22.d[0]
With q18 being pushed and popped off the stack in the prologue and epilogue of the function!
These are large files from SPEC that I haven't been able to analyse yet as to why GCC even attempts
to do that, but with this patch it doesn't try to load a register and overwrite all its lanes.
This patch shaves off about 5k of code size from zeusmp on aarch64 at -O3, so I believe it's a good
thing to do.
* simplify-rtx.c (simplify_ternary_operation): Simplify vec_merge
of two vec_duplicates into a vec_concat.
From-SVN: r254550
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 18 |
2 files changed, 23 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b50bca..37ccb2c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2017-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + * simplify-rtx.c (simplify_ternary_operation): Simplify vec_merge + of two vec_duplicates into a vec_concat. + +2017-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + * simplify-rtx.c (simplify_ternary_operation, VEC_MERGE): Simplify vec_merge of vec_duplicate and vec_concat. * config/aarch64/constraints.md (Utq): New constraint. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 92c783a..e1a16a4 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -5784,6 +5784,24 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode, if (!side_effects_p (otherop)) return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1); } + + /* Replace (vec_merge (vec_duplicate x) (vec_duplicate y) + (const_int n)) + with (vec_concat x y) or (vec_concat y x) depending on value + of N. */ + if (GET_CODE (op0) == VEC_DUPLICATE + && GET_CODE (op1) == VEC_DUPLICATE + && GET_MODE_NUNITS (GET_MODE (op0)) == 2 + && GET_MODE_NUNITS (GET_MODE (op1)) == 2 + && IN_RANGE (sel, 1, 2)) + { + rtx newop0 = XEXP (op0, 0); + rtx newop1 = XEXP (op1, 0); + if (sel == 2) + std::swap (newop0, newop1); + + return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1); + } } if (rtx_equal_p (op0, op1) |