[PATCHv2,rs6000] Merge two vector shift when their sources are the same
Checks
Commit Message
Hi,
This patch merges two "vsldoi" insns when their sources are the
same. Particularly, it is simplified to be one move if the total
shift is multiples of 16 bytes.
Bootstrapped and tested on powerpc64-linux BE and LE with no
regressions.
Thanks
Gui Haochen
ChangeLog
2023-02-28 Haochen Gui <guihaoc@linux.ibm.com>
gcc/
* config/rs6000/altivec.md (*altivec_vsldoi_dup_<mode>): New
insn_and_split to merge two vsldoi when the sources are the same.
gcc/testsuite/
* gcc.target/powerpc/vsldoi_merge.c: New.
patch.diff
Comments
Hi
Gently ping this.
https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612944.html
Thanks
Gui Haochen
在 2023/2/28 10:31, HAO CHEN GUI 写道:
> Hi,
> This patch merges two "vsldoi" insns when their sources are the
> same. Particularly, it is simplified to be one move if the total
> shift is multiples of 16 bytes.
>
> Bootstrapped and tested on powerpc64-linux BE and LE with no
> regressions.
>
> Thanks
> Gui Haochen
>
>
> ChangeLog
> 2023-02-28 Haochen Gui <guihaoc@linux.ibm.com>
>
> gcc/
> * config/rs6000/altivec.md (*altivec_vsldoi_dup_<mode>): New
> insn_and_split to merge two vsldoi when the sources are the same.
>
> gcc/testsuite/
> * gcc.target/powerpc/vsldoi_merge.c: New.
>
>
>
> patch.diff
> diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
> index 84660073f32..fae8ec2b2e8 100644
> --- a/gcc/config/rs6000/altivec.md
> +++ b/gcc/config/rs6000/altivec.md
> @@ -2529,6 +2529,35 @@ (define_insn "altivec_vsldoi_<mode>"
> "vsldoi %0,%1,%2,%3"
> [(set_attr "type" "vecperm")])
>
> +(define_insn_and_split "*altivec_vsldoi_dup_<mode>"
> + [(set (match_operand:VM 0 "register_operand" "=v")
> + (unspec:VM [(unspec:VM [(match_operand:VM 1 "register_operand" "v")
> + (match_dup 1)
> + (match_operand:QI 2 "immediate_operand" "i")]
> + UNSPEC_VSLDOI)
> + (unspec:VM [(match_dup 1)
> + (match_dup 1)
> + (match_dup 2)]
> + UNSPEC_VSLDOI)
> + (match_operand:QI 3 "immediate_operand" "i")]
> + UNSPEC_VSLDOI))]
> + "TARGET_ALTIVEC"
> + "#"
> + "&& 1"
> + [(const_int 0)]
> +{
> + unsigned int shift1 = UINTVAL (operands[2]);
> + unsigned int shift2 = UINTVAL (operands[3]);
> +
> + unsigned int shift = (shift1 + shift2) % 16;
> + if (shift)
> + emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1],
> + operands[1], GEN_INT (shift)));
> + else
> + emit_move_insn (operands[0], operands[1]);
> + DONE;
> +})
> +
> (define_insn "altivec_vupkhs<VU_char>"
> [(set (match_operand:VP 0 "register_operand" "=v")
> (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
> diff --git a/gcc/testsuite/gcc.target/powerpc/vsldoi_merge.c b/gcc/testsuite/gcc.target/powerpc/vsldoi_merge.c
> new file mode 100644
> index 00000000000..eebd7b4d382
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/vsldoi_merge.c
> @@ -0,0 +1,59 @@
> +/* { dg-do run } */
> +/* { dg-require-effective-target powerpc_vsx_ok } */
> +/* { dg-options "-O2 -mvsx -save-temps" } */
> +
> +#include "altivec.h"
> +
> +#ifdef DEBUG
> +#include <stdio.h>
> +#endif
> +
> +void abort (void);
> +
> +__attribute__ ((noipa)) vector signed int
> +test1 (vector signed int a)
> +{
> + a = vec_sld (a, a, 2);
> + a = vec_sld (a, a, 6);
> + return a;
> +}
> +
> +__attribute__ ((noipa)) vector signed int
> +test2 (vector signed int a)
> +{
> + a = vec_sld (a, a, 14);
> + a = vec_sld (a, a, 2);
> + return a;
> +}
> +
> +int main (void)
> +{
> + vector signed int a = {1,2,3,4};
> + vector signed int result_a;
> + int i;
> +
> + result_a = test1 (a);
> + vector signed int expect_a = {3,4,1,2};
> +
> + for (i = 0; i< 4; i++)
> + if (result_a[i] != expect_a[i])
> +#ifdef DEBUG
> + printf("ERROR: test1 result[%d] = %d, not expected[%d] = %d\n",
> + i, result_a[i], i, expect_a[i]);
> +#else
> + abort ();
> +#endif
> +
> + result_a = test2 (a);
> +
> + for (i = 0; i< 4; i++)
> + if (result_a[i] != a[i])
> +#ifdef DEBUG
> + printf("ERROR: test2 result[%d] = %d, not expected[%d] = %d\n",
> + i, result_a[i], i, a[i]);
> +#else
> + abort ();
> +#endif
> +}
> +
> +/* { dg-final { scan-assembler-times {\mvsldoi\M} 1 } } */
@@ -2529,6 +2529,35 @@ (define_insn "altivec_vsldoi_<mode>"
"vsldoi %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
+(define_insn_and_split "*altivec_vsldoi_dup_<mode>"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_dup 1)
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_VSLDOI)
+ (unspec:VM [(match_dup 1)
+ (match_dup 1)
+ (match_dup 2)]
+ UNSPEC_VSLDOI)
+ (match_operand:QI 3 "immediate_operand" "i")]
+ UNSPEC_VSLDOI))]
+ "TARGET_ALTIVEC"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ unsigned int shift1 = UINTVAL (operands[2]);
+ unsigned int shift2 = UINTVAL (operands[3]);
+
+ unsigned int shift = (shift1 + shift2) % 16;
+ if (shift)
+ emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1],
+ operands[1], GEN_INT (shift)));
+ else
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
(define_insn "altivec_vupkhs<VU_char>"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
new file mode 100644
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx -save-temps" } */
+
+#include "altivec.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+void abort (void);
+
+__attribute__ ((noipa)) vector signed int
+test1 (vector signed int a)
+{
+ a = vec_sld (a, a, 2);
+ a = vec_sld (a, a, 6);
+ return a;
+}
+
+__attribute__ ((noipa)) vector signed int
+test2 (vector signed int a)
+{
+ a = vec_sld (a, a, 14);
+ a = vec_sld (a, a, 2);
+ return a;
+}
+
+int main (void)
+{
+ vector signed int a = {1,2,3,4};
+ vector signed int result_a;
+ int i;
+
+ result_a = test1 (a);
+ vector signed int expect_a = {3,4,1,2};
+
+ for (i = 0; i< 4; i++)
+ if (result_a[i] != expect_a[i])
+#ifdef DEBUG
+ printf("ERROR: test1 result[%d] = %d, not expected[%d] = %d\n",
+ i, result_a[i], i, expect_a[i]);
+#else
+ abort ();
+#endif
+
+ result_a = test2 (a);
+
+ for (i = 0; i< 4; i++)
+ if (result_a[i] != a[i])
+#ifdef DEBUG
+ printf("ERROR: test2 result[%d] = %d, not expected[%d] = %d\n",
+ i, result_a[i], i, a[i]);
+#else
+ abort ();
+#endif
+}
+
+/* { dg-final { scan-assembler-times {\mvsldoi\M} 1 } } */