* config/i386/i386.md (paritydi2, paritysi2): New expanders.
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Feb 2007 21:08:25 +0000 (21:08 +0000)
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Feb 2007 21:08:25 +0000 (21:08 +0000)
        (paritydi2_cmp, paritydi2_cmp): New insn and split patterns.
        (*parityhi2_cmp, *parityqi2_cmp): New insn patterns.

testsuite/ChangeLog:

        * gcc.target/i386/parity-1.c: New test.
        * gcc.target/i386/parity-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121863 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/parity-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/parity-2.c [new file with mode: 0644]

index bd541e5..0b40844 100644 (file)
@@ -1,3 +1,9 @@
+2007-02-12  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386.md (paritydi2, paritysi2): New expanders.
+       (paritydi2_cmp, paritydi2_cmp): New insn and split patterns.
+       (*parityhi2_cmp, *parityqi2_cmp): New insn patterns.
+
 2007-02-12  Eric Botcazou  <ebotcazou@adacore.com>
 
        * tree.h (DECL_IGNORED_P): Document further effect for FUNCTION_DECL.
        mode.
        * config/rs6000/rs6000.c (rs6000_builtin_conversion): New.
        (TARGET_VECTORIZE_BUILTIN_CONVERSION): Defined.
-       (rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX or
-       ALTIVEC_BUILTIN_VCFSX.
+       (rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX
+       or ALTIVEC_BUILTIN_VCFSX.
 
 2007-02-10  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
index 04d0136..5e39568 100644 (file)
   [(set_attr "prefix_rep" "1")
    (set_attr "type" "bitmanip")
    (set_attr "mode" "HI")])
+
+(define_expand "paritydi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (parity:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
+  "! TARGET_POPCNT"
+{
+  rtx scratch = gen_reg_rtx (QImode);
+  rtx cond;
+
+  emit_insn (gen_paritydi2_cmp (NULL_RTX, NULL_RTX,
+                               NULL_RTX, operands[1]));
+
+  cond = gen_rtx_fmt_ee (ORDERED, QImode,
+                        gen_rtx_REG (CCmode, FLAGS_REG),
+                        const0_rtx);
+  emit_insn (gen_rtx_SET (VOIDmode, scratch, cond));
+
+  if (TARGET_64BIT)
+    emit_insn (gen_zero_extendqidi2 (operands[0], scratch));
+  else
+    {
+      rtx tmp = gen_reg_rtx (SImode);
+
+      emit_insn (gen_zero_extendqisi2 (tmp, scratch));
+      emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+    }
+  DONE;
+})
+
+(define_insn_and_split "paritydi2_cmp"
+  [(set (reg:CC FLAGS_REG)
+       (parity:CC (match_operand:DI 3 "nonimmediate_operand" "0,m")))
+   (clobber (match_scratch:DI 0 "=r,X"))
+   (clobber (match_scratch:SI 1 "=r,r"))
+   (clobber (match_scratch:HI 2 "=Q,Q"))]
+  "! TARGET_POPCNT"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 1)
+          (xor:SI (match_dup 1) (match_dup 4)))
+      (clobber (reg:CC FLAGS_REG))])
+   (parallel
+     [(set (reg:CC FLAGS_REG)
+          (parity:CC (match_dup 1)))
+      (clobber (match_dup 1))
+      (clobber (match_dup 2))])]
+{
+  operands[4] = gen_lowpart (SImode, operands[3]);
+
+  if (MEM_P (operands[3]))
+    emit_move_insn (operands[1], gen_highpart (SImode, operands[3]));
+  else if (! TARGET_64BIT)
+    operands[1] = gen_highpart (SImode, operands[3]);
+  else
+    {
+      emit_move_insn (operands[1], gen_lowpart (SImode, operands[3]));
+      emit_insn (gen_lshrdi3 (operands[3], operands[3], GEN_INT (32)));
+    }
+})
+
+(define_expand "paritysi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (parity:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
+  "! TARGET_POPCNT"
+{
+  rtx scratch = gen_reg_rtx (QImode);
+  rtx cond;
+
+  emit_insn (gen_paritysi2_cmp (NULL_RTX, NULL_RTX, operands[1]));
+
+  cond = gen_rtx_fmt_ee (ORDERED, QImode,
+                        gen_rtx_REG (CCmode, FLAGS_REG),
+                        const0_rtx);
+  emit_insn (gen_rtx_SET (VOIDmode, scratch, cond));
+
+  emit_insn (gen_zero_extendqisi2 (operands[0], scratch));
+  DONE;
+})
+
+(define_insn_and_split "paritysi2_cmp"
+  [(set (reg:CC FLAGS_REG)
+       (parity:CC (match_operand:SI 2 "nonimmediate_operand" "0,m")))
+   (clobber (match_scratch:SI 0 "=r,X"))
+   (clobber (match_scratch:HI 1 "=Q,Q"))]
+  "! TARGET_POPCNT"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 1)
+          (xor:HI (match_dup 1) (match_dup 3)))
+      (clobber (reg:CC FLAGS_REG))])
+   (parallel
+     [(set (reg:CC FLAGS_REG)
+          (parity:CC (match_dup 1)))
+      (clobber (match_dup 1))])]
+{
+  operands[3] = gen_lowpart (HImode, operands[2]);
+
+  if (MEM_P (operands[2]))
+    emit_move_insn (operands[1], gen_highpart (HImode, operands[2]));
+  else
+    {
+      emit_move_insn (operands[1], gen_lowpart (HImode, operands[2]));
+      emit_insn (gen_lshrsi3 (operands[2], operands[2], GEN_INT (16)));
+    }
+})
+
+(define_insn "*parityhi2_cmp"
+  [(set (reg:CC FLAGS_REG)
+       (parity:CC (match_operand:HI 1 "register_operand" "0")))
+   (clobber (match_scratch:HI 0 "=Q"))]
+  "! TARGET_POPCNT"
+  "xor{b}\t{%h0, %b0|%b0, %h0}"
+  [(set_attr "length" "2")
+   (set_attr "mode" "HI")])
+
+(define_insn "*parityqi2_cmp"
+  [(set (reg:CC FLAGS_REG)
+       (parity:CC (match_operand:QI 0 "register_operand" "q")))]
+  "! TARGET_POPCNT"
+  "test{b}\t%0, %0"
+  [(set_attr "length" "2")
+   (set_attr "mode" "QI")])
 \f
 ;; Thread-local storage patterns for ELF.
 ;;
index 2edb100..a2edb27 100644 (file)
@@ -1,3 +1,8 @@
+2007-02-12  Uros Bizjak  <ubizjak@gmail.com>
+
+       * gcc.target/i386/parity-1.c: New test.
+       * gcc.target/i386/parity-2.c: New test.
+
 2007-02-12  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.target/i386/builtin-bswap-3.c: New test case.
diff --git a/gcc/testsuite/gcc.target/i386/parity-1.c b/gcc/testsuite/gcc.target/i386/parity-1.c
new file mode 100644 (file)
index 0000000..f6c881b
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "setnp" } } */
+
+int foo(unsigned int x)
+{
+  return __builtin_parity(x);
+}
diff --git a/gcc/testsuite/gcc.target/i386/parity-2.c b/gcc/testsuite/gcc.target/i386/parity-2.c
new file mode 100644 (file)
index 0000000..cb7855a
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "setnp" } } */
+
+int foo(unsigned long long int x)
+{
+  return __builtin_parityll(x);
+}