Commit dd7a40e1 by Michael Meissner Committed by Michael Meissner

vector.md (xor<mode>3): Move 128-bit boolean expanders to rs6000.md.

[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
parent 9b69d4b4
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> 2013-07-23 David Holsgrove <david.holsgrove@xilinx.com>
* config/microblaze/microblaze.c (microblaze_expand_prologue): * config/microblaze/microblaze.c (microblaze_expand_prologue):
......
...@@ -1040,59 +1040,7 @@ ...@@ -1040,59 +1040,7 @@
[(set_attr "type" "veccomplex")]) [(set_attr "type" "veccomplex")])
;; logical ops. Have the logical ops follow the memory ops in ;; Vector pack/unpack
;; 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")])
(define_insn "altivec_vpkpx" (define_insn "altivec_vpkpx"
[(set (match_operand:V8HI 0 "register_operand" "=v") [(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v") (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
......
...@@ -138,6 +138,7 @@ extern rtx rs6000_address_for_fpconvert (rtx); ...@@ -138,6 +138,7 @@ extern rtx rs6000_address_for_fpconvert (rtx);
extern rtx rs6000_address_for_altivec (rtx); extern rtx rs6000_address_for_altivec (rtx);
extern rtx rs6000_allocate_stack_temp (enum machine_mode, bool, bool); extern rtx rs6000_allocate_stack_temp (enum machine_mode, bool, bool);
extern int rs6000_loop_align (rtx); extern int rs6000_loop_align (rtx);
extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool, rtx);
#endif /* RTX_CODE */ #endif /* RTX_CODE */
#ifdef TREE_CODE #ifdef TREE_CODE
......
...@@ -30139,6 +30139,280 @@ rs6000_set_up_by_prologue (struct hard_reg_set_container *set) ...@@ -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); add_to_hard_reg_set (&set->set, Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
} }
/* 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;
}
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rs6000.h" #include "gt-rs6000.h"
...@@ -1121,14 +1121,11 @@ enum data_align { align_abi, align_opt, align_both }; ...@@ -1121,14 +1121,11 @@ enum data_align { align_abi, align_opt, align_both };
#define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N) #define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N)
/* Alternate name for any vector register supporting logical operations, no /* Alternate name for any vector register supporting logical operations, no
matter which instruction set(s) are available. For 64-bit mode, we also matter which instruction set(s) are available. Allow GPRs as well as the
allow logical operations in the GPRS. This is to allow atomic quad word vector registers. */
builtins not to need the VSX registers for lqarx/stqcx. It also helps with
__int128_t arguments that are passed in GPRs. */
#define VLOGICAL_REGNO_P(N) \ #define VLOGICAL_REGNO_P(N) \
(ALTIVEC_REGNO_P (N) \ (INT_REGNO_P (N) || ALTIVEC_REGNO_P (N) \
|| (TARGET_VSX && FP_REGNO_P (N)) \ || (TARGET_VSX && FP_REGNO_P (N))) \
|| (TARGET_VSX && TARGET_POWERPC64 && INT_REGNO_P (N)))
/* Return number of consecutive hard regs needed starting at reg REGNO /* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE. */ to hold something of mode MODE. */
......
...@@ -391,6 +391,77 @@ ...@@ -391,6 +391,77 @@
(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT") (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
(DF "TARGET_DOUBLE_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")])
;; Start with fixed-point load and store insns. Here we put only the more ;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later. ;; complex forms. Basic data transfer is done later.
...@@ -1840,7 +1911,19 @@ ...@@ -1840,7 +1911,19 @@
FAIL; 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") [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
"" ""
...@@ -7962,10 +8045,19 @@ ...@@ -7962,10 +8045,19 @@
[(parallel [(parallel
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_operand:DI 1 "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 ""))])] (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" (define_insn "anddi3_mc"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r") [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
...@@ -8146,11 +8238,17 @@ ...@@ -8146,11 +8238,17 @@
(define_expand "iordi3" (define_expand "iordi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
(ior:DI (match_operand:DI 1 "gpc_reg_operand" "") (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "reg_or_logical_cint_operand" "")))] (match_operand:DI 2 "reg_or_cint_operand" "")))]
"TARGET_POWERPC64" ""
"
{ {
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; HOST_WIDE_INT value;
rtx tmp = ((!can_create_pseudo_p () rtx tmp = ((!can_create_pseudo_p ()
...@@ -8164,15 +8262,21 @@ ...@@ -8164,15 +8262,21 @@
emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff))); emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
DONE; DONE;
} }
}") })
(define_expand "xordi3" (define_expand "xordi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
(xor:DI (match_operand:DI 1 "gpc_reg_operand" "") (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "reg_or_logical_cint_operand" "")))] (match_operand:DI 2 "reg_or_cint_operand" "")))]
"TARGET_POWERPC64" ""
"
{ {
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)) if (non_logical_cint_operand (operands[2], DImode))
{ {
HOST_WIDE_INT value; HOST_WIDE_INT value;
...@@ -8187,7 +8291,7 @@ ...@@ -8187,7 +8291,7 @@
emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff))); emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
DONE; DONE;
} }
}") })
(define_insn "*booldi3_internal1" (define_insn "*booldi3_internal1"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
...@@ -8425,6 +8529,372 @@ ...@@ -8425,6 +8529,372 @@
(set_attr "length" "4")]) (set_attr "length" "4")])
;; 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"))))])
;; Now define ways of moving data around. ;; Now define ways of moving data around.
;; Set up a register with a value from the GOT table ;; Set up a register with a value from the GOT table
......
...@@ -710,87 +710,6 @@ ...@@ -710,87 +710,6 @@
"") "")
;; 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 ;; Vector count leading zeros
(define_expand "clz<mode>2" (define_expand "clz<mode>2"
[(set (match_operand:VEC_I 0 "register_operand" "") [(set (match_operand:VEC_I 0 "register_operand" "")
......
...@@ -36,10 +36,6 @@ ...@@ -36,10 +36,6 @@
;; Iterator for logical types supported by VSX ;; Iterator for logical types supported by VSX
(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI]) (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 ;; Iterator for memory move. Handle TImode specially to allow
;; it to use gprs as well as vsx registers. ;; it to use gprs as well as vsx registers.
(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF]) (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
...@@ -1047,370 +1043,6 @@ ...@@ -1047,370 +1043,6 @@
(set_attr "fp_type" "<VSfptype_simple>")]) (set_attr "fp_type" "<VSfptype_simple>")])
;; 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")])
;; Permute operations ;; Permute operations
;; Build a V2DF/V2DI vector from two scalars ;; Build a V2DF/V2DI vector from two scalars
......
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> 2013-07-23 Yufeng Zhang <yufeng.zhang@arm.com>
* gcc.target/aarch64/vect_smlal_1.c: Replace 'long' with 'long long'. * gcc.target/aarch64/vect_smlal_1.c: Replace 'long' with 'long long'.
......
/* { 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"
/* { 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"
/* { 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"
/* { 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"
/* 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 */
/* { 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"
/* { 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"
/* { 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"
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment