vector.md (xor<mode>3): Move 128-bit boolean expanders to rs6000.md.
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Tue, 23 Jul 2013 21:19:03 +0000 (21:19 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Tue, 23 Jul 2013 21:19:03 +0000 (21:19 +0000)
[gcc]
2013-07-23  Michael Meissner  <meissner@linux.vnet.ibm.com>

* config/rs6000/vector.md (xor<mode>3): Move 128-bit boolean
expanders to rs6000.md.
(ior<mode>3): Likewise.
(and<mode>3): Likewise.
(one_cmpl<mode>2): Likewise.
(nor<mode>3): Likewise.
(andc<mode>3): Likewise.
(eqv<mode>3): Likewise.
(nand<mode>3): Likewise.
(orc<mode>3): Likewise.

* config/rs6000/rs6000-protos.h (rs6000_split_logical): New
declaration.

* config/rs6000/rs6000.c (rs6000_split_logical_inner): Add support
to split multi-word logical operations.
(rs6000_split_logical_di): Likewise.
(rs6000_split_logical): Likewise.

* config/rs6000/vsx.md (VSX_L2): Delete, no longer used.
(vsx_and<mode>3_32bit): Move 128-bit logical insns to rs6000.md,
and allow TImode operations in 32-bit.
(vsx_and<mode>3_64bit): Likewise.
(vsx_ior<mode>3_32bit): Likewise.
(vsx_ior<mode>3_64bit): Likewise.
(vsx_xor<mode>3_32bit): Likewise.
(vsx_xor<mode>3_64bit): Likewise.
(vsx_one_cmpl<mode>2_32bit): Likewise.
(vsx_one_cmpl<mode>2_64bit): Likewise.
(vsx_nor<mode>3_32bit): Likewise.
(vsx_nor<mode>3_64bit): Likewise.
(vsx_andc<mode>3_32bit): Likewise.
(vsx_andc<mode>3_64bit): Likewise.
(vsx_eqv<mode>3_32bit): Likewise.
(vsx_eqv<mode>3_64bit): Likewise.
(vsx_nand<mode>3_32bit): Likewise.
(vsx_nand<mode>3_64bit): Likewise.
(vsx_orc<mode>3_32bit): Likewise.
(vsx_orc<mode>3_64bit): Likewise.

* config/rs6000/rs6000.h (VLOGICAL_REGNO_P): Always allow vector
logical types in GPRs.

* config/rs6000/altivec.md (altivec_and<mode>3): Move 128-bit
logical insns to rs6000.md, and allow TImode operations in
32-bit.
(altivec_ior<mode>3): Likewise.
(altivec_xor<mode>3): Likewise.
(altivec_one_cmpl<mode>2): Likewise.
(altivec_nor<mode>3): Likewise.
(altivec_andc<mode>3): Likewise.

* config/rs6000/rs6000.md (BOOL_128): New mode iterators and mode
attributes for moving the 128-bit logical operations into
rs6000.md.
(BOOL_REGS_OUTPUT): Likewise.
(BOOL_REGS_OP1): Likewise.
(BOOL_REGS_OP2): Likewise.
(BOOL_REGS_UNARY): Likewise.
(BOOL_REGS_AND_CR0): Likewise.
(one_cmpl<mode>2): Add support for DI logical operations on
32-bit, splitting the operations to 32-bit.
(anddi3): Likewise.
(iordi3): Likewise.
(xordi3): Likewise.
(and<mode>3, 128-bit types): Rewrite 2013-06-06 logical operator
changes to combine the 32/64-bit code, allow logical operations on
TI mode in 32-bit, and to use similar match_operator patterns like
scalar mode uses.  Combine the Altivec and VSX code for logical
operations, and move it here.
(ior<mode>3, 128-bit types): Likewise.
(xor<mode>3, 128-bit types): Likewise.
(one_cmpl<mode>3, 128-bit types): Likewise.
(nor<mode>3, 128-bit types): Likewise.
(andc<mode>3, 128-bit types): Likewise.
(eqv<mode>3, 128-bit types): Likewise.
(nand<mode>3, 128-bit types): Likewise.
(orc<mode>3, 128-bit types): Likewise.
(and<mode>3_internal): Likewise.
(bool<mode>3_internal): Likewise.
(boolc<mode>3_internal1): Likewise.
(boolc<mode>3_internal2): Likewise.
(boolcc<mode>3_internal1): Likewise.
(boolcc<mode>3_internal2): Likewise.
(eqv<mode>3_internal1): Likewise.
(eqv<mode>3_internal2): Likewise.
(one_cmpl1<mode>3_internal): Likewise.

[gcc/testsuite]
2013-07-23  Michael Meissner  <meissner@linux.vnet.ibm.com>

* gcc.target/powerpc/bool2.h: New file, test the code generation
of logical operations for power5, altivec, power7, and power8
systems.
* gcc.target/powerpc/bool2-p5.c: Likewise.
* gcc.target/powerpc/bool2-av.c: Likewise.
* gcc.target/powerpc/bool2-p7.c: Likewise.
* gcc.target/powerpc/bool2-p8.c: Likewise.
* gcc.target/powerpc/bool3.h: Likewise.
* gcc.target/powerpc/bool3-av.c: Likewise.
* gcc.target/powerpc/bool2-p7.c: Likewise.
* gcc.target/powerpc/bool2-p8.c: Likewise.

From-SVN: r201187

18 files changed:
gcc/ChangeLog
gcc/config/rs6000/altivec.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/vector.md
gcc/config/rs6000/vsx.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/bool2-av.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool2-p5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool2-p7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool2-p8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool2.h [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool3-av.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool3-p7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool3-p8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/bool3.h [new file with mode: 0644]

index 16c6b775fa0fe007751f0e23e693ecfe7f09e1c7..fe3e041a00485d0fb56df6c99dc985e82f52537d 100644 (file)
@@ -1,3 +1,93 @@
+2013-07-23  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * config/rs6000/vector.md (xor<mode>3): Move 128-bit boolean
+       expanders to rs6000.md.
+       (ior<mode>3): Likewise.
+       (and<mode>3): Likewise.
+       (one_cmpl<mode>2): Likewise.
+       (nor<mode>3): Likewise.
+       (andc<mode>3): Likewise.
+       (eqv<mode>3): Likewise.
+       (nand<mode>3): Likewise.
+       (orc<mode>3): Likewise.
+
+       * config/rs6000/rs6000-protos.h (rs6000_split_logical): New
+       declaration.
+
+       * config/rs6000/rs6000.c (rs6000_split_logical_inner): Add support
+       to split multi-word logical operations.
+       (rs6000_split_logical_di): Likewise.
+       (rs6000_split_logical): Likewise.
+
+       * config/rs6000/vsx.md (VSX_L2): Delete, no longer used.
+       (vsx_and<mode>3_32bit): Move 128-bit logical insns to rs6000.md,
+       and allow TImode operations in 32-bit.
+       (vsx_and<mode>3_64bit): Likewise.
+       (vsx_ior<mode>3_32bit): Likewise.
+       (vsx_ior<mode>3_64bit): Likewise.
+       (vsx_xor<mode>3_32bit): Likewise.
+       (vsx_xor<mode>3_64bit): Likewise.
+       (vsx_one_cmpl<mode>2_32bit): Likewise.
+       (vsx_one_cmpl<mode>2_64bit): Likewise.
+       (vsx_nor<mode>3_32bit): Likewise.
+       (vsx_nor<mode>3_64bit): Likewise.
+       (vsx_andc<mode>3_32bit): Likewise.
+       (vsx_andc<mode>3_64bit): Likewise.
+       (vsx_eqv<mode>3_32bit): Likewise.
+       (vsx_eqv<mode>3_64bit): Likewise.
+       (vsx_nand<mode>3_32bit): Likewise.
+       (vsx_nand<mode>3_64bit): Likewise.
+       (vsx_orc<mode>3_32bit): Likewise.
+       (vsx_orc<mode>3_64bit): Likewise.
+
+       * config/rs6000/rs6000.h (VLOGICAL_REGNO_P): Always allow vector
+       logical types in GPRs.
+
+       * config/rs6000/altivec.md (altivec_and<mode>3): Move 128-bit
+       logical insns to rs6000.md, and allow TImode operations in
+       32-bit.
+       (altivec_ior<mode>3): Likewise.
+       (altivec_xor<mode>3): Likewise.
+       (altivec_one_cmpl<mode>2): Likewise.
+       (altivec_nor<mode>3): Likewise.
+       (altivec_andc<mode>3): Likewise.
+
+       * config/rs6000/rs6000.md (BOOL_128): New mode iterators and mode
+       attributes for moving the 128-bit logical operations into
+       rs6000.md.
+       (BOOL_REGS_OUTPUT): Likewise.
+       (BOOL_REGS_OP1): Likewise.
+       (BOOL_REGS_OP2): Likewise.
+       (BOOL_REGS_UNARY): Likewise.
+       (BOOL_REGS_AND_CR0): Likewise.
+       (one_cmpl<mode>2): Add support for DI logical operations on
+       32-bit, splitting the operations to 32-bit.
+       (anddi3): Likewise.
+       (iordi3): Likewise.
+       (xordi3): Likewise.
+       (and<mode>3, 128-bit types): Rewrite 2013-06-06 logical operator
+       changes to combine the 32/64-bit code, allow logical operations on
+       TI mode in 32-bit, and to use similar match_operator patterns like
+       scalar mode uses.  Combine the Altivec and VSX code for logical
+       operations, and move it here.
+       (ior<mode>3, 128-bit types): Likewise.
+       (xor<mode>3, 128-bit types): Likewise.
+       (one_cmpl<mode>3, 128-bit types): Likewise.
+       (nor<mode>3, 128-bit types): Likewise.
+       (andc<mode>3, 128-bit types): Likewise.
+       (eqv<mode>3, 128-bit types): Likewise.
+       (nand<mode>3, 128-bit types): Likewise.
+       (orc<mode>3, 128-bit types): Likewise.
+       (and<mode>3_internal): Likewise.
+       (bool<mode>3_internal): Likewise.
+       (boolc<mode>3_internal1): Likewise.
+       (boolc<mode>3_internal2): Likewise.
+       (boolcc<mode>3_internal1): Likewise.
+       (boolcc<mode>3_internal2): Likewise.
+       (eqv<mode>3_internal1): Likewise.
+       (eqv<mode>3_internal2): Likewise.
+       (one_cmpl1<mode>3_internal): Likewise.
+
 2013-07-23  David Holsgrove <david.holsgrove@xilinx.com>
 
        * config/microblaze/microblaze.c (microblaze_expand_prologue):
index 6607e450be3289f00c6d7b361767d0b6cf0dfcc7..db2e93a168a51d1be1e23cf6421a5b2747ced376 100644 (file)
   [(set_attr "type" "veccomplex")])
 
 
-;; logical ops.  Have the logical ops follow the memory ops in
-;; terms of whether to prefer VSX or Altivec
-
-;; AND has a clobber to be consistant with VSX, which adds splitters for using
-;; the GPR registers.
-(define_insn "*altivec_and<mode>3"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-        (and:VM (match_operand:VM 1 "register_operand" "v")
-               (match_operand:VM 2 "register_operand" "v")))
-   (clobber (match_scratch:CC 3 "=X"))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vand %0,%1,%2"
-  [(set_attr "type" "vecsimple")])
-
-(define_insn "*altivec_ior<mode>3"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-        (ior:VM (match_operand:VM 1 "register_operand" "v")
-               (match_operand:VM 2 "register_operand" "v")))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vor %0,%1,%2"
-  [(set_attr "type" "vecsimple")])
-
-(define_insn "*altivec_xor<mode>3"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-        (xor:VM (match_operand:VM 1 "register_operand" "v")
-               (match_operand:VM 2 "register_operand" "v")))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vxor %0,%1,%2"
-  [(set_attr "type" "vecsimple")])
-
-(define_insn "*altivec_one_cmpl<mode>2"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-        (not:VM (match_operand:VM 1 "register_operand" "v")))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vnor %0,%1,%1"
-  [(set_attr "type" "vecsimple")])
-  
-(define_insn "*altivec_nor<mode>3"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-       (and:VM (not:VM (match_operand:VM 1 "register_operand" "v"))
-               (not:VM (match_operand:VM 2 "register_operand" "v"))))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vnor %0,%1,%2"
-  [(set_attr "type" "vecsimple")])
-
-(define_insn "*altivec_andc<mode>3"
-  [(set (match_operand:VM 0 "register_operand" "=v")
-        (and:VM (not:VM (match_operand:VM 2 "register_operand" "v"))
-               (match_operand:VM 1 "register_operand" "v")))]
-  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-  "vandc %0,%1,%2"
-  [(set_attr "type" "vecsimple")])
-
+;; Vector pack/unpack
 (define_insn "altivec_vpkpx"
   [(set (match_operand:V8HI 0 "register_operand" "=v")
         (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
index 25bad1bfb6872a4991294481ba12845ddc21aa8b..3a7b37a827063c1182abb7dee88ab045a3f3c793 100644 (file)
@@ -138,6 +138,7 @@ extern rtx rs6000_address_for_fpconvert (rtx);
 extern rtx rs6000_address_for_altivec (rtx);
 extern rtx rs6000_allocate_stack_temp (enum machine_mode, bool, bool);
 extern int rs6000_loop_align (rtx);
+extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool, rtx);
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
index 646eedcc79d0568ef955047a941ca12ae49c97b7..8c3cf97faa3a993f2c386905172500eb2182d77f 100644 (file)
@@ -30139,6 +30139,280 @@ rs6000_set_up_by_prologue (struct hard_reg_set_container *set)
     add_to_hard_reg_set (&set->set, Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
 }
 
+\f
+/* Helper function for rs6000_split_logical to emit a logical instruction after
+   spliting the operation to single GPR registers.
+
+   DEST is the destination register.
+   OP1 and OP2 are the input source registers.
+   CODE is the base operation (AND, IOR, XOR, NOT).
+   MODE is the machine mode.
+   If COMPLEMENT_FINAL_P is true, wrap the whole operation with NOT.
+   If COMPLEMENT_OP1_P is true, wrap operand1 with NOT.
+   If COMPLEMENT_OP2_P is true, wrap operand2 with NOT.
+   CLOBBER_REG is either NULL or a scratch register of type CC to allow
+   formation of the AND instructions.  */
+
+static void
+rs6000_split_logical_inner (rtx dest,
+                           rtx op1,
+                           rtx op2,
+                           enum rtx_code code,
+                           enum machine_mode mode,
+                           bool complement_final_p,
+                           bool complement_op1_p,
+                           bool complement_op2_p,
+                           rtx clobber_reg)
+{
+  rtx bool_rtx;
+  rtx set_rtx;
+
+  /* Optimize AND of 0/0xffffffff and IOR/XOR of 0.  */
+  if (op2 && GET_CODE (op2) == CONST_INT
+      && (mode == SImode || (mode == DImode && TARGET_POWERPC64))
+      && !complement_final_p && !complement_op1_p && !complement_op2_p)
+    {
+      HOST_WIDE_INT mask = GET_MODE_MASK (mode);
+      HOST_WIDE_INT value = INTVAL (op2) & mask;
+
+      /* Optimize AND of 0 to just set 0.  Optimize AND of -1 to be a move.  */
+      if (code == AND)
+       {
+         if (value == 0)
+           {
+             emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+             return;
+           }
+
+         else if (value == mask)
+           {
+             if (!rtx_equal_p (dest, op1))
+               emit_insn (gen_rtx_SET (VOIDmode, dest, op1));
+             return;
+           }
+       }
+
+      /* Optimize IOR/XOR of 0 to be a simple move.  Split large operations
+        into separate ORI/ORIS or XORI/XORIS instrucitons.  */
+      else if (code == IOR || code == XOR)
+       {
+         if (value == 0)
+           {
+             if (!rtx_equal_p (dest, op1))
+               emit_insn (gen_rtx_SET (VOIDmode, dest, op1));
+             return;
+           }
+       }
+    }
+
+  if (complement_op1_p)
+    op1 = gen_rtx_NOT (mode, op1);
+
+  if (complement_op2_p)
+    op2 = gen_rtx_NOT (mode, op2);
+
+  bool_rtx = ((code == NOT)
+             ? gen_rtx_NOT (mode, op1)
+             : gen_rtx_fmt_ee (code, mode, op1, op2));
+
+  if (complement_final_p)
+    bool_rtx = gen_rtx_NOT (mode, bool_rtx);
+
+  set_rtx = gen_rtx_SET (VOIDmode, dest, bool_rtx);
+
+  /* Is this AND with an explicit clobber?  */
+  if (clobber_reg)
+    {
+      rtx clobber = gen_rtx_CLOBBER (VOIDmode, clobber_reg);
+      set_rtx = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set_rtx, clobber));
+    }
+
+  emit_insn (set_rtx);
+  return;
+}
+
+/* Split a DImode AND/IOR/XOR with a constant on a 32-bit system.  These
+   operations are split immediately during RTL generation to allow for more
+   optimizations of the AND/IOR/XOR.
+
+   OPERANDS is an array containing the destination and two input operands.
+   CODE is the base operation (AND, IOR, XOR, NOT).
+   MODE is the machine mode.
+   If COMPLEMENT_FINAL_P is true, wrap the whole operation with NOT.
+   If COMPLEMENT_OP1_P is true, wrap operand1 with NOT.
+   If COMPLEMENT_OP2_P is true, wrap operand2 with NOT.
+   CLOBBER_REG is either NULL or a scratch register of type CC to allow
+   formation of the AND instructions.  */
+
+static void
+rs6000_split_logical_di (rtx operands[3],
+                        enum rtx_code code,
+                        bool complement_final_p,
+                        bool complement_op1_p,
+                        bool complement_op2_p,
+                        rtx clobber_reg)
+{
+  const HOST_WIDE_INT lower_32bits = HOST_WIDE_INT_C(0xffffffff);
+  const HOST_WIDE_INT upper_32bits = ~ lower_32bits;
+  const HOST_WIDE_INT sign_bit = HOST_WIDE_INT_C(0x80000000);
+  enum hi_lo { hi = 0, lo = 1 };
+  rtx op0_hi_lo[2], op1_hi_lo[2], op2_hi_lo[2];
+  size_t i;
+
+  op0_hi_lo[hi] = gen_highpart (SImode, operands[0]);
+  op1_hi_lo[hi] = gen_highpart (SImode, operands[1]);
+  op0_hi_lo[lo] = gen_lowpart (SImode, operands[0]);
+  op1_hi_lo[lo] = gen_lowpart (SImode, operands[1]);
+
+  if (code == NOT)
+    op2_hi_lo[hi] = op2_hi_lo[lo] = NULL_RTX;
+  else
+    {
+      if (GET_CODE (operands[2]) != CONST_INT)
+       {
+         op2_hi_lo[hi] = gen_highpart_mode (SImode, DImode, operands[2]);
+         op2_hi_lo[lo] = gen_lowpart (SImode, operands[2]);
+       }
+      else
+       {
+         HOST_WIDE_INT value = INTVAL (operands[2]);
+         HOST_WIDE_INT value_hi_lo[2];
+
+         gcc_assert (!complement_final_p);
+         gcc_assert (!complement_op1_p);
+         gcc_assert (!complement_op2_p);
+
+         value_hi_lo[hi] = value >> 32;
+         value_hi_lo[lo] = value & lower_32bits;
+
+         for (i = 0; i < 2; i++)
+           {
+             HOST_WIDE_INT sub_value = value_hi_lo[i];
+
+             if (sub_value & sign_bit)
+               sub_value |= upper_32bits;
+
+             op2_hi_lo[i] = GEN_INT (sub_value);
+
+             /* If this is an AND instruction, check to see if we need to load
+                the value in a register.  */
+             if (code == AND && sub_value != -1 && sub_value != 0
+                 && !and_operand (op2_hi_lo[i], SImode))
+               op2_hi_lo[i] = force_reg (SImode, op2_hi_lo[i]);
+           }
+       }
+    }
+
+  for (i = 0; i < 2; i++)
+    {
+      /* Split large IOR/XOR operations.  */
+      if ((code == IOR || code == XOR)
+         && GET_CODE (op2_hi_lo[i]) == CONST_INT
+         && !complement_final_p
+         && !complement_op1_p
+         && !complement_op2_p
+         && clobber_reg == NULL_RTX
+         && !logical_const_operand (op2_hi_lo[i], SImode))
+       {
+         HOST_WIDE_INT value = INTVAL (op2_hi_lo[i]);
+         HOST_WIDE_INT hi_16bits = value & HOST_WIDE_INT_C(0xffff0000);
+         HOST_WIDE_INT lo_16bits = value & HOST_WIDE_INT_C(0x0000ffff);
+         rtx tmp = gen_reg_rtx (SImode);
+
+         /* Make sure the constant is sign extended.  */
+         if ((hi_16bits & sign_bit) != 0)
+           hi_16bits |= upper_32bits;
+
+         rs6000_split_logical_inner (tmp, op1_hi_lo[i], GEN_INT (hi_16bits),
+                                     code, SImode, false, false, false,
+                                     NULL_RTX);
+
+         rs6000_split_logical_inner (op0_hi_lo[i], tmp, GEN_INT (lo_16bits),
+                                     code, SImode, false, false, false,
+                                     NULL_RTX);
+       }
+      else
+       rs6000_split_logical_inner (op0_hi_lo[i], op1_hi_lo[i], op2_hi_lo[i],
+                                   code, SImode, complement_final_p,
+                                   complement_op1_p, complement_op2_p,
+                                   clobber_reg);
+    }
+
+  return;
+}
+
+/* Split the insns that make up boolean operations operating on multiple GPR
+   registers.  The boolean MD patterns ensure that the inputs either are
+   exactly the same as the output registers, or there is no overlap.
+
+   OPERANDS is an array containing the destination and two input operands.
+   CODE is the base operation (AND, IOR, XOR, NOT).
+   MODE is the machine mode.
+   If COMPLEMENT_FINAL_P is true, wrap the whole operation with NOT.
+   If COMPLEMENT_OP1_P is true, wrap operand1 with NOT.
+   If COMPLEMENT_OP2_P is true, wrap operand2 with NOT.
+   CLOBBER_REG is either NULL or a scratch register of type CC to allow
+   formation of the AND instructions.  */
+
+void
+rs6000_split_logical (rtx operands[3],
+                     enum rtx_code code,
+                     bool complement_final_p,
+                     bool complement_op1_p,
+                     bool complement_op2_p,
+                     rtx clobber_reg)
+{
+  enum machine_mode mode = GET_MODE (operands[0]);
+  enum machine_mode sub_mode;
+  rtx op0, op1, op2;
+  int sub_size, regno0, regno1, nregs, i;
+
+  /* If this is DImode, use the specialized version that can run before
+     register allocation.  */
+  if (mode == DImode && !TARGET_POWERPC64)
+    {
+      rs6000_split_logical_di (operands, code, complement_final_p,
+                              complement_op1_p, complement_op2_p,
+                              clobber_reg);
+      return;
+    }
+
+  op0 = operands[0];
+  op1 = operands[1];
+  op2 = (code == NOT) ? NULL_RTX : operands[2];
+  sub_mode = (TARGET_POWERPC64) ? DImode : SImode;
+  sub_size = GET_MODE_SIZE (sub_mode);
+  regno0 = REGNO (op0);
+  regno1 = REGNO (op1);
+
+  gcc_assert (reload_completed);
+  gcc_assert (IN_RANGE (regno0, FIRST_GPR_REGNO, LAST_GPR_REGNO));
+  gcc_assert (IN_RANGE (regno1, FIRST_GPR_REGNO, LAST_GPR_REGNO));
+
+  nregs = rs6000_hard_regno_nregs[(int)mode][regno0];
+  gcc_assert (nregs > 1);
+
+  if (op2 && REG_P (op2))
+    gcc_assert (IN_RANGE (REGNO (op2), FIRST_GPR_REGNO, LAST_GPR_REGNO));
+
+  for (i = 0; i < nregs; i++)
+    {
+      int offset = i * sub_size;
+      rtx sub_op0 = simplify_subreg (sub_mode, op0, mode, offset);
+      rtx sub_op1 = simplify_subreg (sub_mode, op1, mode, offset);
+      rtx sub_op2 = ((code == NOT)
+                    ? NULL_RTX
+                    : simplify_subreg (sub_mode, op2, mode, offset));
+
+      rs6000_split_logical_inner (sub_op0, sub_op1, sub_op2, code, sub_mode,
+                                 complement_final_p, complement_op1_p,
+                                 complement_op2_p, clobber_reg);
+    }
+
+  return;
+}
+
+\f
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rs6000.h"
index 8e96fbf356bc84a7162df4926a7ac76cdc2920c3..e5a6abd6d0d140ff409b2fb01bcb3379c906ed5a 100644 (file)
@@ -1121,14 +1121,11 @@ enum data_align { align_abi, align_opt, align_both };
 #define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N)
 
 /* Alternate name for any vector register supporting logical operations, no
-   matter which instruction set(s) are available.  For 64-bit mode, we also
-   allow logical operations in the GPRS.  This is to allow atomic quad word
-   builtins not to need the VSX registers for lqarx/stqcx.  It also helps with
-   __int128_t arguments that are passed in GPRs.  */
+   matter which instruction set(s) are available.  Allow GPRs as well as the
+   vector registers.  */
 #define VLOGICAL_REGNO_P(N)                                            \
-  (ALTIVEC_REGNO_P (N)                                                 \
-   || (TARGET_VSX && FP_REGNO_P (N))                                   \
-   || (TARGET_VSX && TARGET_POWERPC64 && INT_REGNO_P (N)))
+  (INT_REGNO_P (N) || ALTIVEC_REGNO_P (N)                              \
+   || (TARGET_VSX && FP_REGNO_P (N)))                                  \
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.  */
index 372c8138fc6b74d7bc14cc1d07cda5416a4f3c98..064a51da608248c9a59d3aa0dfd37815e8eea19c 100644 (file)
 
 (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
                                (DF "TARGET_DOUBLE_FLOAT")])
+
+;; Mode iterator for logical operations on 128-bit types
+(define_mode_iterator BOOL_128         [TI
+                                        PTI
+                                        (V16QI "TARGET_ALTIVEC")
+                                        (V8HI  "TARGET_ALTIVEC")
+                                        (V4SI  "TARGET_ALTIVEC")
+                                        (V4SF  "TARGET_ALTIVEC")
+                                        (V2DI  "TARGET_ALTIVEC")
+                                        (V2DF  "TARGET_ALTIVEC")])
+
+;; For the GPRs we use 3 constraints for register outputs, two that are the
+;; same as the output register, and a third where the output register is an
+;; early clobber, so we don't have to deal with register overlaps.  For the
+;; vector types, we prefer to use the vector registers.  For TI mode, allow
+;; either.
+
+;; Mode attribute for boolean operation register constraints for output
+(define_mode_attr BOOL_REGS_OUTPUT     [(TI    "&r,r,r,wa,v")
+                                        (PTI   "&r,r,r")
+                                        (V16QI "wa,v,&?r,?r,?r")
+                                        (V8HI  "wa,v,&?r,?r,?r")
+                                        (V4SI  "wa,v,&?r,?r,?r")
+                                        (V4SF  "wa,v,&?r,?r,?r")
+                                        (V2DI  "wa,v,&?r,?r,?r")
+                                        (V2DF  "wa,v,&?r,?r,?r")])
+
+;; Mode attribute for boolean operation register constraints for operand1
+(define_mode_attr BOOL_REGS_OP1                [(TI    "r,0,r,wa,v")
+                                        (PTI   "r,0,r")
+                                        (V16QI "wa,v,r,0,r")
+                                        (V8HI  "wa,v,r,0,r")
+                                        (V4SI  "wa,v,r,0,r")
+                                        (V4SF  "wa,v,r,0,r")
+                                        (V2DI  "wa,v,r,0,r")
+                                        (V2DF  "wa,v,r,0,r")])
+
+;; Mode attribute for boolean operation register constraints for operand2
+(define_mode_attr BOOL_REGS_OP2                [(TI    "r,r,0,wa,v")
+                                        (PTI   "r,r,0")
+                                        (V16QI "wa,v,r,r,0")
+                                        (V8HI  "wa,v,r,r,0")
+                                        (V4SI  "wa,v,r,r,0")
+                                        (V4SF  "wa,v,r,r,0")
+                                        (V2DI  "wa,v,r,r,0")
+                                        (V2DF  "wa,v,r,r,0")])
+
+;; Mode attribute for boolean operation register constraints for operand1
+;; for one_cmpl.  To simplify things, we repeat the constraint where 0
+;; is used for operand1 or operand2
+(define_mode_attr BOOL_REGS_UNARY      [(TI    "r,0,0,wa,v")
+                                        (PTI   "r,0,0")
+                                        (V16QI "wa,v,r,0,0")
+                                        (V8HI  "wa,v,r,0,0")
+                                        (V4SI  "wa,v,r,0,0")
+                                        (V4SF  "wa,v,r,0,0")
+                                        (V2DI  "wa,v,r,0,0")
+                                        (V2DF  "wa,v,r,0,0")])
+
+;; Mode attribute for the clobber of CC0 for AND expansion.
+;; For the 128-bit types, we never do AND immediate, but we need to
+;; get the correct number of X's for the number of operands.
+(define_mode_attr BOOL_REGS_AND_CR0    [(TI    "X,X,X,X,X")
+                                        (PTI   "X,X,X")
+                                        (V16QI "X,X,X,X,X")
+                                        (V8HI  "X,X,X,X,X")
+                                        (V4SI  "X,X,X,X,X")
+                                        (V4SF  "X,X,X,X,X")
+                                        (V2DI  "X,X,X,X,X")
+                                        (V2DF  "X,X,X,X,X")])
+
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
     FAIL;
 })
 
-(define_insn "one_cmpl<mode>2"
+(define_expand "one_cmpl<mode>2"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
+  ""
+{
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX);
+      DONE;
+    }
+})
+
+(define_insn "*one_cmpl<mode>2"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
   [(parallel
     [(set (match_operand:DI 0 "gpc_reg_operand" "")
          (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                 (match_operand:DI 2 "and64_2_operand" "")))
+                 (match_operand:DI 2 "reg_or_cint_operand" "")))
      (clobber (match_scratch:CC 3 ""))])]
-  "TARGET_POWERPC64"
-  "")
+  ""
+{
+  if (!TARGET_POWERPC64)
+    {
+      rtx cc = gen_rtx_SCRATCH (CCmode);
+      rs6000_split_logical (operands, AND, false, false, false, cc);
+      DONE;
+    }
+  else if (!and64_2_operand (operands[2], DImode))
+    operands[2] = force_reg (DImode, operands[2]);
+})
 
 (define_insn "anddi3_mc"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
 (define_expand "iordi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_logical_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "
+               (match_operand:DI 2 "reg_or_cint_operand" "")))]
+  ""
 {
-  if (non_logical_cint_operand (operands[2], DImode))
+  if (!TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, IOR, false, false, false, NULL_RTX);
+      DONE;
+    }
+  else if (!reg_or_logical_cint_operand (operands[2], DImode))
+    operands[2] = force_reg (DImode, operands[2]);
+  else if (non_logical_cint_operand (operands[2], DImode))
     {
       HOST_WIDE_INT value;
       rtx tmp = ((!can_create_pseudo_p ()
       emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
-}")
+})
 
 (define_expand "xordi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_logical_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "
+               (match_operand:DI 2 "reg_or_cint_operand" "")))]
+  ""
 {
+  if (!TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, XOR, false, false, false, NULL_RTX);
+      DONE;
+    }
+  else if (!reg_or_logical_cint_operand (operands[2], DImode))
+    operands[2] = force_reg (DImode, operands[2]);
   if (non_logical_cint_operand (operands[2], DImode))
     {
       HOST_WIDE_INT value;
       emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
-}")
+})
 
 (define_insn "*booldi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
   [(set_attr "type" "integer")
    (set_attr "length" "4")])
 
+\f
+;; 128-bit logical operations expanders
+
+(define_expand "and<mode>3"
+  [(parallel [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+                  (and:BOOL_128
+                   (match_operand:BOOL_128 1 "vlogical_operand" "")
+                   (match_operand:BOOL_128 2 "vlogical_operand" "")))
+             (clobber (match_scratch:CC 3 ""))])]
+  ""
+  "")
+
+(define_expand "ior<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+        (ior:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
+                     (match_operand:BOOL_128 2 "vlogical_operand" "")))]
+  ""
+  "")
+
+(define_expand "xor<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+        (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
+                     (match_operand:BOOL_128 2 "vlogical_operand" "")))]
+  ""
+  "")
+
+(define_expand "one_cmpl<mode>2"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+        (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))]
+  ""
+  "")
+
+(define_expand "nor<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+       (and:BOOL_128
+        (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" ""))
+        (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
+  ""
+  "")
+
+(define_expand "andc<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+        (and:BOOL_128
+        (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))
+        (match_operand:BOOL_128 1 "vlogical_operand" "")))]
+  ""
+  "")
+
+;; Power8 vector logical instructions.
+(define_expand "eqv<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+       (not:BOOL_128
+        (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
+                      (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
+  "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
+  "")
+
+;; Rewrite nand into canonical form
+(define_expand "nand<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+       (ior:BOOL_128
+        (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" ""))
+        (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
+  "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
+  "")
+
+;; The canonical form is to have the negated element first, so we need to
+;; reverse arguments.
+(define_expand "orc<mode>3"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+       (ior:BOOL_128
+        (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))
+        (match_operand:BOOL_128 1 "vlogical_operand" "")))]
+  "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
+  "")
+
+;; 128-bit logical operations insns and split operations
+(define_insn_and_split "*and<mode>3_internal"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+        (and:BOOL_128
+        (match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>")
+        (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")))
+   (clobber (match_scratch:CC 3 "<BOOL_REGS_AND_CR0>"))]
+  ""
+{
+  if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
+    return "xxland %x0,%x1,%x2";
+
+  if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
+    return "vand %0,%1,%2";
+
+  return "#";
+}
+  "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, AND, false, false, false, operands[3]);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
+;; 128-bit IOR/XOR
+(define_insn_and_split "*bool<mode>3_internal"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+       (match_operator:BOOL_128 3 "boolean_or_operator"
+        [(match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>")
+         (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")]))]
+  ""
+{
+  if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
+    return "xxl%q3 %x0,%x1,%x2";
+
+  if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
+    return "v%q3 %0,%1,%2";
+
+  return "#";
+}
+  "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, false,
+                       NULL_RTX);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
+;; 128-bit ANDC/ORC
+(define_insn_and_split "*boolc<mode>3_internal1"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+       (match_operator:BOOL_128 3 "boolean_operator"
+        [(not:BOOL_128
+          (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP1>"))
+         (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP2>")]))]
+  "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)"
+{
+  if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
+    return "xxl%q3 %x0,%x1,%x2";
+
+  if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
+    return "v%q3 %0,%1,%2";
+
+  return "#";
+}
+  "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND))
+   && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false,
+                       NULL_RTX);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
+(define_insn_and_split "*boolc<mode>3_internal2"
+  [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
+       (match_operator:TI2 3 "boolean_operator"
+        [(not:TI2
+          (match_operand:TI2 1 "int_reg_operand" "r,0,r"))
+         (match_operand:TI2 2 "int_reg_operand" "r,r,0")]))]
+  "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
+  "#"
+  "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false,
+                       NULL_RTX);
+  DONE;
+}
+  [(set_attr "type" "integer")
+   (set (attr "length")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16")))])
+
+;; 128-bit NAND/NOR
+(define_insn_and_split "*boolcc<mode>3_internal1"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+       (match_operator:BOOL_128 3 "boolean_operator"
+        [(not:BOOL_128
+          (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>"))
+         (not:BOOL_128
+          (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))]))]
+  "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)"
+{
+  if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
+    return "xxl%q3 %x0,%x1,%x2";
+
+  if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
+    return "v%q3 %0,%1,%2";
+
+  return "#";
+}
+  "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND))
+   && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true,
+                       NULL_RTX);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
+(define_insn_and_split "*boolcc<mode>3_internal2"
+  [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
+       (match_operator:TI2 3 "boolean_operator"
+        [(not:TI2
+          (match_operand:TI2 1 "int_reg_operand" "r,0,r"))
+         (not:TI2
+          (match_operand:TI2 2 "int_reg_operand" "r,r,0"))]))]
+  "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
+  "#"
+  "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true,
+                       NULL_RTX);
+  DONE;
+}
+  [(set_attr "type" "integer")
+   (set (attr "length")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16")))])
+
+
+;; 128-bit EQV
+(define_insn_and_split "*eqv<mode>3_internal1"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+       (not:BOOL_128
+        (xor:BOOL_128
+         (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>")
+         (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))))]
+  "TARGET_P8_VECTOR"
+{
+  if (vsx_register_operand (operands[0], <MODE>mode))
+    return "xxleqv %x0,%x1,%x2";
+
+  return "#";
+}
+  "TARGET_P8_VECTOR && reload_completed
+   && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
+(define_insn_and_split "*eqv<mode>3_internal2"
+  [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
+       (not:TI2
+        (xor:TI2
+         (match_operand:TI2 1 "int_reg_operand" "r,0,r")
+         (match_operand:TI2 2 "int_reg_operand" "r,r,0"))))]
+  "!TARGET_P8_VECTOR"
+  "#"
+  "reload_completed && !TARGET_P8_VECTOR"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX);
+  DONE;
+}
+  [(set_attr "type" "integer")
+   (set (attr "length")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16")))])
+
+;; 128-bit one's complement
+(define_insn_and_split "*one_cmpl<mode>3_internal"
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
+       (not:BOOL_128
+         (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_UNARY>")))]
+  ""
+{
+  if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
+    return "xxlnor %x0,%x1,%x1";
+
+  if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
+    return "vnor %0,%1,%1";
+
+  return "#";
+}
+  "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
+  [(const_int 0)]
+{
+  rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX);
+  DONE;
+}
+  [(set (attr "type")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "vecsimple")
+       (const_string "integer")))
+   (set (attr "length")
+      (if_then_else
+       (match_test "vsx_register_operand (operands[0], <MODE>mode)")
+       (const_string "4")
+       (if_then_else
+        (match_test "TARGET_POWERPC64")
+        (const_string "8")
+        (const_string "16"))))])
+
 \f
 ;; Now define ways of moving data around.
 
index 6cfebdeebdc29b13b94b48b533fbec997be1d154..2eaa2d325c3566a2452b3d175089658f3284582c 100644 (file)
   "")
 
 \f
-;; Vector logical instructions
-;; Do not support TImode logical instructions on 32-bit at present, because the
-;; compiler will see that we have a TImode and when it wanted DImode, and
-;; convert the DImode to TImode, store it on the stack, and load it in a VSX
-;; register.
-(define_expand "xor<mode>3"
-  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-        (xor:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
-                  (match_operand:VEC_L 2 "vlogical_operand" "")))]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-(define_expand "ior<mode>3"
-  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-        (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
-                  (match_operand:VEC_L 2 "vlogical_operand" "")))]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-(define_expand "and<mode>3"
-  [(parallel [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-                  (and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
-                             (match_operand:VEC_L 2 "vlogical_operand" "")))
-             (clobber (match_scratch:CC 3 ""))])]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-(define_expand "one_cmpl<mode>2"
-  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-        (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-(define_expand "nor<mode>3"
-  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-       (and:VEC_L (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" ""))
-                  (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))))]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-(define_expand "andc<mode>3"
-  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-        (and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
-                  (match_operand:VEC_L 1 "vlogical_operand" "")))]
-  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)"
-  "")
-
-;; Power8 vector logical instructions.
-(define_expand "eqv<mode>3"
-  [(set (match_operand:VEC_L 0 "register_operand" "")
-       (not:VEC_L
-        (xor:VEC_L (match_operand:VEC_L 1 "register_operand" "")
-                   (match_operand:VEC_L 2 "register_operand" ""))))]
-  "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)")
-
-;; Rewrite nand into canonical form
-(define_expand "nand<mode>3"
-  [(set (match_operand:VEC_L 0 "register_operand" "")
-       (ior:VEC_L
-        (not:VEC_L (match_operand:VEC_L 1 "register_operand" ""))
-        (not:VEC_L (match_operand:VEC_L 2 "register_operand" ""))))]
-  "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)")
-
-;; The canonical form is to have the negated elment first, so we need to
-;; reverse arguments.
-(define_expand "orc<mode>3"
-  [(set (match_operand:VEC_L 0 "register_operand" "")
-       (ior:VEC_L
-        (not:VEC_L (match_operand:VEC_L 1 "register_operand" ""))
-        (match_operand:VEC_L 2 "register_operand" "")))]
-  "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
-   && (<MODE>mode != TImode || TARGET_POWERPC64)")
-
 ;; Vector count leading zeros
 (define_expand "clz<mode>2"
   [(set (match_operand:VEC_I 0 "register_operand" "")
index b87da826a95d8415481ae620c1bea6e6878a75b1..5e6f397031ccf95ce2ce9b8579e8e8d5d05a6a89 100644 (file)
 ;; Iterator for logical types supported by VSX
 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
 
-;; Like VSX_L, but don't support TImode for doing logical instructions in
-;; 32-bit
-(define_mode_iterator VSX_L2 [V16QI V8HI V4SI V2DI V4SF V2DF])
-
 ;; Iterator for memory move.  Handle TImode specially to allow
 ;; it to use gprs as well as vsx registers.
 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
   [(set_attr "type" "<VStype_simple>")
    (set_attr "fp_type" "<VSfptype_simple>")])
 
-\f
-;; Logical operations.  Do not support TImode logical instructions on 32-bit at
-;; present, because the compiler will see that we have a TImode and when it
-;; wanted DImode, and convert the DImode to TImode, store it on the stack, and
-;; load it in a VSX register or generate extra logical instructions in GPR
-;; registers.
-
-;; When we are splitting the operations to GPRs, we use three alternatives, two
-;; where the first/second inputs and output are in the same register, and the
-;; third where the output specifies an early clobber so that we don't have to
-;; worry about overlapping registers.
-
-(define_insn "*vsx_and<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-        (and:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
-                   (match_operand:VSX_L2 2 "vlogical_operand" "wa")))
-   (clobber (match_scratch:CC 3 "X"))]
-  "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxland %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_and<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r")
-        (and:VSX_L
-        (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r")
-        (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r")))
-   (clobber (match_scratch:CC 3 "X,X,X,X"))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxland %x0,%x1,%x2
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(parallel [(set (match_dup 4) (and:DI (match_dup 5) (match_dup 6)))
-             (clobber (match_dup 3))])
-   (parallel [(set (match_dup 7) (and:DI (match_dup 8) (match_dup 9)))
-             (clobber (match_dup 3))])]
-{
-  operands[4] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[7] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[9] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
-(define_insn "*vsx_ior<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-        (ior:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
-                   (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
-  "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlor %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_ior<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r,?r,&?r")
-        (ior:VSX_L
-        (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r,0,r")
-        (match_operand:VSX_L 2 "vsx_reg_or_cint_operand" "wa,r,0,r,n,n")))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlor %x0,%x1,%x2
-   #
-   #
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(const_int 0)]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-
-  if (operands[5] == constm1_rtx)
-    emit_move_insn (operands[3], constm1_rtx);
-
-  else if (operands[5] == const0_rtx)
-    {
-      if (!rtx_equal_p (operands[3], operands[4]))
-       emit_move_insn (operands[3], operands[4]);
-    }
-  else
-    emit_insn (gen_iordi3 (operands[3], operands[4], operands[5]));
-
-  if (operands[8] == constm1_rtx)
-    emit_move_insn (operands[8], constm1_rtx);
-
-  else if (operands[8] == const0_rtx)
-    {
-      if (!rtx_equal_p (operands[6], operands[7]))
-       emit_move_insn (operands[6], operands[7]);
-    }
-  else
-    emit_insn (gen_iordi3 (operands[6], operands[7], operands[8]));
-  DONE;
-}
-  [(set_attr "type" "vecsimple,two,two,two,three,three")
-   (set_attr "length" "4,8,8,8,16,16")])
-
-(define_insn "*vsx_xor<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-        (xor:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "%wa")
-                   (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
-  "VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_POWERPC64"
-  "xxlxor %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_xor<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r,?r,&?r")
-        (xor:VSX_L
-        (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r,0,r")
-        (match_operand:VSX_L 2 "vsx_reg_or_cint_operand" "wa,r,0,r,n,n")))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlxor %x0,%x1,%x2
-   #
-   #
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (xor:DI (match_dup 4) (match_dup 5)))
-   (set (match_dup 6) (xor:DI (match_dup 7) (match_dup 8)))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two,three,three")
-   (set_attr "length" "4,8,8,8,16,16")])
-
-(define_insn "*vsx_one_cmpl<mode>2_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-        (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa")))]
-  "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlnor %x0,%x1,%x1"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_one_cmpl<mode>2_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,&?r")
-        (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r")))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlnor %x0,%x1,%x1
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 2) (not:DI (match_dup 3)))
-   (set (match_dup 4) (not:DI (match_dup 5)))]
-{
-  operands[2] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[3] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[5] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two")
-   (set_attr "length" "4,8,8")])
-  
-(define_insn "*vsx_nor<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-       (and:VSX_L2
-        (not:VSX_L2 (match_operand:VSX_L 1 "vlogical_operand" "%wa"))
-        (not:VSX_L2 (match_operand:VSX_L 2 "vlogical_operand" "wa"))))]
-  "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlnor %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_nor<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,&?r")
-       (and:VSX_L
-        (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "%wa,0,r,r"))
-        (not:VSX_L (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r"))))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlnor %x0,%x1,%x2
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (and:DI (not:DI (match_dup 4)) (not:DI (match_dup 5))))
-   (set (match_dup 6) (and:DI (not:DI (match_dup 7)) (not:DI (match_dup 8))))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
-(define_insn "*vsx_andc<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-        (and:VSX_L2
-        (not:VSX_L2
-         (match_operand:VSX_L2 2 "vlogical_operand" "wa"))
-        (match_operand:VSX_L2 1 "vlogical_operand" "wa")))]
-  "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlandc %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_andc<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
-        (and:VSX_L
-        (not:VSX_L
-         (match_operand:VSX_L 2 "vlogical_operand" "wa,0,r,r"))
-        (match_operand:VSX_L 1 "vlogical_operand" "wa,r,0,r")))]
-  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlandc %x0,%x1,%x2
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (and:DI (not:DI (match_dup 4)) (match_dup 5)))
-   (set (match_dup 6) (and:DI (not:DI (match_dup 7)) (match_dup 8)))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
-;; Power8 vector logical instructions.
-(define_insn "*vsx_eqv<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-       (not:VSX_L2
-        (xor:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa")
-                    (match_operand:VSX_L2 2 "vlogical_operand" "wa"))))]
-  "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxleqv %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_eqv<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
-       (not:VSX_L
-        (xor:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r,r")
-                   (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r"))))]
-  "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxleqv %x0,%x1,%x2
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
-   && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (not:DI (xor:DI (match_dup 4) (match_dup 5))))
-   (set (match_dup 6) (not:DI (xor:DI (match_dup 7) (match_dup 8))))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
-;; Rewrite nand into canonical form
-(define_insn "*vsx_nand<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-       (ior:VSX_L2
-        (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa"))
-        (not:VSX_L2 (match_operand:VSX_L2 2 "vlogical_operand" "wa"))))]
-  "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlnand %x0,%x1,%x2"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_nand<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "register_operand" "=wa,?r,?r,?r")
-       (ior:VSX_L
-        (not:VSX_L (match_operand:VSX_L 1 "register_operand" "wa,0,r,r"))
-        (not:VSX_L (match_operand:VSX_L 2 "register_operand" "wa,r,0,r"))))]
-  "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlnand %x0,%x1,%x2
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
-   && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (ior:DI (not:DI (match_dup 4)) (not:DI (match_dup 5))))
-   (set (match_dup 6) (ior:DI (not:DI (match_dup 7)) (not:DI (match_dup 8))))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
-;; Rewrite or complement into canonical form, by reversing the arguments
-(define_insn "*vsx_orc<mode>3_32bit"
-  [(set (match_operand:VSX_L2 0 "vlogical_operand" "=wa")
-       (ior:VSX_L2
-        (not:VSX_L2 (match_operand:VSX_L2 1 "vlogical_operand" "wa"))
-        (match_operand:VSX_L2 2 "vlogical_operand" "wa")))]
-  "!TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "xxlorc %x0,%x2,%x1"
-  [(set_attr "type" "vecsimple")
-   (set_attr "length" "4")])
-
-(define_insn_and_split "*vsx_orc<mode>3_64bit"
-  [(set (match_operand:VSX_L 0 "vlogical_operand" "=wa,?r,?r,?r")
-       (ior:VSX_L
-        (not:VSX_L (match_operand:VSX_L 1 "vlogical_operand" "wa,0,r,r"))
-        (match_operand:VSX_L 2 "vlogical_operand" "wa,r,0,r")))]
-  "TARGET_POWERPC64 && TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)"
-  "@
-   xxlorc %x0,%x2,%x1
-   #
-   #
-   #"
-  "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR
-   && VECTOR_MEM_VSX_P (<MODE>mode)
-   && int_reg_operand (operands[0], <MODE>mode)"
-  [(set (match_dup 3) (ior:DI (not:DI (match_dup 4)) (match_dup 5)))
-   (set (match_dup 6) (ior:DI (not:DI (match_dup 7)) (match_dup 8)))]
-{
-  operands[3] = simplify_subreg (DImode, operands[0], <MODE>mode, 0);
-  operands[4] = simplify_subreg (DImode, operands[1], <MODE>mode, 0);
-  operands[5] = simplify_subreg (DImode, operands[2], <MODE>mode, 0);
-  operands[6] = simplify_subreg (DImode, operands[0], <MODE>mode, 8);
-  operands[7] = simplify_subreg (DImode, operands[1], <MODE>mode, 8);
-  operands[8] = simplify_subreg (DImode, operands[2], <MODE>mode, 8);
-}
-  [(set_attr "type" "vecsimple,two,two,two")
-   (set_attr "length" "4,8,8,8")])
-
 \f
 ;; Permute operations
 
index 0a5dd8bc47e81b7f1904d82961a8202a468a239c..7b24942e113538ee3e3d04da131583b6ee1907f2 100644 (file)
@@ -1,3 +1,17 @@
+2013-07-23  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/bool2.h: New file, test the code generation
+       of logical operations for power5, altivec, power7, and power8
+       systems.
+       * gcc.target/powerpc/bool2-p5.c: Likewise.
+       * gcc.target/powerpc/bool2-av.c: Likewise.
+       * gcc.target/powerpc/bool2-p7.c: Likewise.
+       * gcc.target/powerpc/bool2-p8.c: Likewise.
+       * gcc.target/powerpc/bool3.h: Likewise.
+       * gcc.target/powerpc/bool3-av.c: Likewise.
+       * gcc.target/powerpc/bool2-p7.c: Likewise.
+       * gcc.target/powerpc/bool2-p8.c: Likewise.
+
 2013-07-23  Yufeng Zhang  <yufeng.zhang@arm.com>
 
        * gcc.target/aarch64/vect_smlal_1.c: Replace 'long' with 'long long'.
diff --git a/gcc/testsuite/gcc.target/powerpc/bool2-av.c b/gcc/testsuite/gcc.target/powerpc/bool2-av.c
new file mode 100644 (file)
index 0000000..fc56ce2
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-O2 -mcpu=power6 -maltivec" } */
+/* { dg-final { scan-assembler-not "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]eqv "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]orc "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nand "    } } */
+/* { dg-final { scan-assembler     "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler     "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler     "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler     "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler     "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+#ifndef TYPE
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+
+#include "bool2.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool2-p5.c b/gcc/testsuite/gcc.target/powerpc/bool2-p5.c
new file mode 100644 (file)
index 0000000..e4810d0
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-O2 -mcpu=power5 -mabi=altivec -mno-altivec -mno-vsx" } */
+/* { dg-final { scan-assembler    "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler    "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler    "\[ \t\]eqv "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]orc "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+#ifndef TYPE
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+
+#include "bool2.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool2-p7.c b/gcc/testsuite/gcc.target/powerpc/bool2-p7.c
new file mode 100644 (file)
index 0000000..274fcb0
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler-not "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]eqv "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]orc "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+#ifndef TYPE
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+
+#include "bool2.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool2-p8.c b/gcc/testsuite/gcc.target/powerpc/bool2-p8.c
new file mode 100644 (file)
index 0000000..34f4d2d
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-O2 -mcpu=power8" } */
+/* { dg-final { scan-assembler-not "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]eqv "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]orc "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]nand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler     "\[ \t\]xxlnand " } } */
+
+#ifndef TYPE
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+
+#include "bool2.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool2.h b/gcc/testsuite/gcc.target/powerpc/bool2.h
new file mode 100644 (file)
index 0000000..4513944
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test various logical operations.  */
+
+TYPE arg1 (TYPE p, TYPE q) { return p & q; }           /* AND  */
+TYPE arg2 (TYPE p, TYPE q) { return p | q; }           /* OR   */
+TYPE arg3 (TYPE p, TYPE q) { return p ^ q; }           /* XOR  */
+TYPE arg4 (TYPE p)        { return ~ p; }              /* NOR  */
+TYPE arg5 (TYPE p, TYPE q) { return ~(p & q); }                /* NAND */
+TYPE arg6 (TYPE p, TYPE q) { return ~(p | q); }                /* NOR  */
+TYPE arg7 (TYPE p, TYPE q) { return ~(p ^ q); }                /* EQV  */
+TYPE arg8 (TYPE p, TYPE q) { return (~p) & q; }                /* ANDC */
+TYPE arg9 (TYPE p, TYPE q) { return (~p) | q; }                /* ORC  */
+TYPE arg10(TYPE p, TYPE q) { return (~p) ^ q; }                /* EQV  */
+TYPE arg11(TYPE p, TYPE q) { return p & (~q); }                /* ANDC */
+TYPE arg12(TYPE p, TYPE q) { return p | (~q); }                /* ORC  */
+TYPE arg13(TYPE p, TYPE q) { return p ^ (~q); }                /* EQV  */
+
+void ptr1 (TYPE *p) { p[0] = p[1] & p[2]; }            /* AND  */
+void ptr2 (TYPE *p) { p[0] = p[1] | p[2]; }            /* OR   */
+void ptr3 (TYPE *p) { p[0] = p[1] ^ p[2]; }            /* XOR  */
+void ptr4 (TYPE *p) { p[0] = ~p[1]; }                  /* NOR  */
+void ptr5 (TYPE *p) { p[0] = ~(p[1] & p[2]); }         /* NAND */
+void ptr6 (TYPE *p) { p[0] = ~(p[1] | p[2]); }         /* NOR  */
+void ptr7 (TYPE *p) { p[0] = ~(p[1] ^ p[2]); }         /* EQV  */
+void ptr8 (TYPE *p) { p[0] = ~(p[1]) & p[2]; }         /* ANDC */
+void ptr9 (TYPE *p) { p[0] = (~p[1]) | p[2]; }         /* ORC  */
+void ptr10(TYPE *p) { p[0] = (~p[1]) ^ p[2]; }         /* EQV  */
+void ptr11(TYPE *p) { p[0] = p[1] & (~p[2]); }         /* ANDC */
+void ptr12(TYPE *p) { p[0] = p[1] | (~p[2]); }         /* ORC  */
+void ptr13(TYPE *p) { p[0] = p[1] ^ (~p[2]); }         /* EQV  */
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-av.c b/gcc/testsuite/gcc.target/powerpc/bool3-av.c
new file mode 100644 (file)
index 0000000..4ef82c8
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-O2 -mcpu=power6 -mabi=altivec -maltivec -mno-vsx" } */
+/* { dg-final { scan-assembler    "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler    "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+/* On altivec, for 128-bit types, ORC/ANDC/EQV might not show up, since the
+   vector unit doesn't support these, so the appropriate combine patterns may
+   not be generated.  */
+
+#ifndef TYPE
+#ifdef _ARCH_PPC64
+#define TYPE __int128_t
+#else
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+#endif
+
+#include "bool3.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p7.c b/gcc/testsuite/gcc.target/powerpc/bool3-p7.c
new file mode 100644 (file)
index 0000000..a077ba5
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler    "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler    "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+/* On power7, for 128-bit types, ORC/ANDC/EQV might not show up, since the
+   vector unit doesn't support these, so the appropriate combine patterns may
+   not be generated.  */
+
+#ifndef TYPE
+#ifdef _ARCH_PPC64
+#define TYPE __int128_t
+#else
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+#endif
+
+#include "bool3.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p8.c b/gcc/testsuite/gcc.target/powerpc/bool3-p8.c
new file mode 100644 (file)
index 0000000..361a045
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-O2 -mcpu=power8" } */
+/* { dg-final { scan-assembler    "\[ \t\]and "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]or "      } } */
+/* { dg-final { scan-assembler    "\[ \t\]xor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nor "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]andc "    } } */
+/* { dg-final { scan-assembler    "\[ \t\]eqv "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]orc "     } } */
+/* { dg-final { scan-assembler    "\[ \t\]nand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vand "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vandc "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vor "     } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vxor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]vnor "    } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxland "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlor "   } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlxor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnor "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlandc " } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxleqv "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlorc "  } } */
+/* { dg-final { scan-assembler-not "\[ \t\]xxlnand " } } */
+
+#ifndef TYPE
+#ifdef _ARCH_PPC64
+#define TYPE __int128_t
+#else
+typedef int v4si __attribute__ ((vector_size (16)));
+#define TYPE v4si
+#endif
+#endif
+
+#include "bool3.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3.h b/gcc/testsuite/gcc.target/powerpc/bool3.h
new file mode 100644 (file)
index 0000000..7b99a4a
--- /dev/null
@@ -0,0 +1,186 @@
+/* Test forcing 128-bit logical types into GPR registers.  */
+
+#if defined(NO_ASM)
+#define FORCE_REG1(X)
+#define FORCE_REG2(X,Y)
+
+#else
+#if defined(USE_ALTIVEC)
+#define REG_CLASS "+v"
+#define PRINT_REG1 "# altivec reg %0"
+#define PRINT_REG2 "# altivec reg %0, %1"
+
+#elif defined(USE_FPR)
+#define REG_CLASS "+d"
+#define PRINT_REG1 "# fpr reg %0"
+#define PRINT_REG2 "# fpr reg %0, %1"
+
+#elif defined(USE_VSX)
+#define REG_CLASS "+wa"
+#define PRINT_REG1 "# vsx reg %x0"
+#define PRINT_REG2 "# vsx reg %x0, %x1"
+
+#else
+#define REG_CLASS "+r"
+#define PRINT_REG1 "# gpr reg %0"
+#define PRINT_REG2 "# gpr reg %0, %1"
+#endif
+
+#define FORCE_REG1(X) __asm__ (PRINT_REG1 : REG_CLASS (X))
+#define FORCE_REG2(X,Y) __asm__ (PRINT_REG2 : REG_CLASS (X), REG_CLASS (Y))
+#endif
+
+void ptr1 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a & b;                                   /* AND */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr2 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a | b;                                   /* OR */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr3 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a ^ b;                                   /* XOR */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr4 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b;
+
+  FORCE_REG1 (a);
+  b = ~a;                                      /* NOR */
+  FORCE_REG1 (b);
+  p[0] = b;
+}
+
+void ptr5 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = ~(a & b);                                           /* NAND */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr6 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = ~(a | b);                                           /* AND */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr7 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = ~(a ^ b);                                           /* EQV */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr8 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = (~a) & b;                                           /* ANDC */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr9 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = (~a) | b;                                           /* ORC */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr10 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = (~a) ^ b;                                           /* EQV */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr11 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a & (~b);                                           /* ANDC */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr12 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a | (~b);                                           /* ORC */
+  FORCE_REG1 (c);
+  p[0] = c;
+}
+
+void ptr13 (TYPE *p)
+{
+  TYPE a = p[1];
+  TYPE b = p[2];
+  TYPE c;
+
+  FORCE_REG2 (a, b);
+  c = a ^ (~b);                                           /* AND */
+  FORCE_REG1 (c);
+  p[0] = c;
+}