[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] aarch64: Add an and/ior-based movk pattern [PR87763]

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:50:37 GMT 2020


https://gcc.gnu.org/g:bba0c624c8b1d6e54dc58091dd21b0c2ab000434

commit bba0c624c8b1d6e54dc58091dd21b0c2ab000434
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Mon Feb 3 21:43:44 2020 +0000

    aarch64: Add an and/ior-based movk pattern [PR87763]
    
    This patch adds a second movk pattern that models the instruction
    as a "normal" and/ior operation rather than an insertion.  It fixes
    the third insv_1.c failure in PR87763, which was a regression from
    GCC 8.
    
    2020-02-06  Richard Sandiford  <richard.sandiford@arm.com>
    
    gcc/
            PR target/87763
            * config/aarch64/aarch64-protos.h (aarch64_movk_shift): Declare.
            * config/aarch64/aarch64.c (aarch64_movk_shift): New function.
            * config/aarch64/aarch64.md (aarch64_movk<mode>): New pattern.
    
    gcc/testsuite/
            PR target/87763
            * gcc.target/aarch64/movk_2.c: New test.

Diff:
---
 gcc/ChangeLog                             |  7 +++
 gcc/config/aarch64/aarch64-protos.h       |  1 +
 gcc/config/aarch64/aarch64.c              | 24 ++++++++++
 gcc/config/aarch64/aarch64.md             | 17 +++++++
 gcc/testsuite/ChangeLog                   |  5 ++
 gcc/testsuite/gcc.target/aarch64/movk_2.c | 78 +++++++++++++++++++++++++++++++
 6 files changed, 132 insertions(+)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index efbbbf08225..cea8ffee99c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2020-02-06  Richard Sandiford  <richard.sandiford@arm.com>
+
+	PR target/87763
+	* config/aarch64/aarch64-protos.h (aarch64_movk_shift): Declare.
+	* config/aarch64/aarch64.c (aarch64_movk_shift): New function.
+	* config/aarch64/aarch64.md (aarch64_movk<mode>): New pattern.
+
 2020-02-06  Richard Sandiford  <richard.sandiford@arm.com>
 
 	PR rtl-optimization/87763
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 24cc65a383a..d29975a8921 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -560,6 +560,7 @@ bool aarch64_sve_float_mul_immediate_p (rtx);
 bool aarch64_split_dimode_const_store (rtx, rtx);
 bool aarch64_symbolic_address_p (rtx);
 bool aarch64_uimm12_shift (HOST_WIDE_INT);
+int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &);
 bool aarch64_use_return_insn_p (void);
 const char *aarch64_output_casesi (rtx *);
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6581e4cb075..6a1b4099af1 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -7895,6 +7895,30 @@ aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode)
 	  || (val & (((HOST_WIDE_INT) 0xffff) << 16)) == val);
 }
 
+/* Test whether:
+
+     X = (X & AND_VAL) | IOR_VAL;
+
+   can be implemented using:
+
+     MOVK X, #(IOR_VAL >> shift), LSL #shift
+
+   Return the shift if so, otherwise return -1.  */
+int
+aarch64_movk_shift (const wide_int_ref &and_val,
+		    const wide_int_ref &ior_val)
+{
+  unsigned int precision = and_val.get_precision ();
+  unsigned HOST_WIDE_INT mask = 0xffff;
+  for (unsigned int shift = 0; shift < precision; shift += 16)
+    {
+      if (and_val == ~mask && (ior_val & mask) == ior_val)
+	return shift;
+      mask <<= 16;
+    }
+  return -1;
+}
+
 /* VAL is a value with the inner mode of MODE.  Replicate it to fill a
    64-bit (DImode) integer.  */
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 90eebce85c0..9c1f17d0f85 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1282,6 +1282,23 @@
   [(set_attr "type" "mov_imm")]
 )
 
+;; Match MOVK as a normal AND and IOR operation.
+(define_insn "aarch64_movk<mode>"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+	(ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
+			  (match_operand:GPI 2 "const_int_operand"))
+		 (match_operand:GPI 3 "const_int_operand")))]
+  "aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
+		       rtx_mode_t (operands[3], <MODE>mode)) >= 0"
+  {
+    int shift = aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
+				    rtx_mode_t (operands[3], <MODE>mode));
+    operands[2] = gen_int_mode (UINTVAL (operands[3]) >> shift, SImode);
+    operands[3] = gen_int_mode (shift, SImode);
+    return "movk\\t%<w>0, #%X2, lsl %3";
+  }
+)
+
 (define_expand "movti"
   [(set (match_operand:TI 0 "nonimmediate_operand")
 	(match_operand:TI 1 "general_operand"))]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 601bc336290..cdb26581b9c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-02-06  Richard Sandiford  <richard.sandiford@arm.com>
+
+	PR target/87763
+	* gcc.target/aarch64/movk_2.c: New test.
+
 2020-02-06  Marek Polacek  <polacek@redhat.com>
 
 	PR c++/93597 - ICE with lambda in operator function.
diff --git a/gcc/testsuite/gcc.target/aarch64/movk_2.c b/gcc/testsuite/gcc.target/aarch64/movk_2.c
new file mode 100644
index 00000000000..a0477ad5d42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/movk_2.c
@@ -0,0 +1,78 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <stdint.h>
+
+#define H3 ((uint64_t) 0xffff << 48)
+#define H2 ((uint64_t) 0xffff << 32)
+#define H1 ((uint64_t) 0xffff << 16)
+#define H0 ((uint64_t) 0xffff)
+
+/*
+** f1:
+**	mov	w0, w1
+**	movk	w0, #0x9876(?:, lsl #?0)?
+**	ret
+*/
+uint32_t
+f1 (uint32_t dummy, uint32_t x)
+{
+  return (x & 0xffff0000) | 0x9876;
+}
+
+/*
+** f2:
+**	movk	w0, #0x1234, lsl #?16
+**	ret
+*/
+uint32_t
+f2 (uint32_t x)
+{
+  return (x & 0xffff) | 0x12340000;
+}
+
+/*
+** g1:
+**	movk	x0, #0x1234, lsl #?0
+**	ret
+*/
+uint64_t
+g1 (uint64_t x)
+{
+  return (x & (H3 | H2 | H1)) | 0x1234;
+}
+
+/*
+** g2:
+**	movk	x0, #0x900e, lsl #?16
+**	ret
+*/
+uint64_t
+g2 (uint64_t x)
+{
+  return (x & (H3 | H2 | H0)) | ((uint64_t) 0x900e << 16);
+}
+
+/*
+** g3:
+**	movk	x0, #0xee33, lsl #?32
+**	ret
+*/
+uint64_t
+g3 (uint64_t x)
+{
+  return (x & (H3 | H1 | H0)) | ((uint64_t) 0xee33 << 32);
+}
+
+/*
+** g4:
+**	mov	x0, x1
+**	movk	x0, #0x7654, lsl #?48
+**	ret
+*/
+uint64_t
+g4 (uint64_t dummy, uint64_t x)
+{
+  return (x & (H2 | H1 | H0)) | ((uint64_t) 0x7654 << 48);
+}


More information about the Gcc-cvs mailing list