Index: gcc/config/rs6000/vector.md =================================================================== --- gcc/config/rs6000/vector.md (revision 201180) +++ gcc/config/rs6000/vector.md (working copy) @@ -710,87 +710,6 @@ (define_expand "cr6_test_for_lt_reverse" "") -;; 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 "xor3" - [(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 != TImode || TARGET_POWERPC64)" - "") - -(define_expand "ior3" - [(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 != TImode || TARGET_POWERPC64)" - "") - -(define_expand "and3" - [(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 != TImode || TARGET_POWERPC64)" - "") - -(define_expand "one_cmpl2" - [(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 != TImode || TARGET_POWERPC64)" - "") - -(define_expand "nor3" - [(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 != TImode || TARGET_POWERPC64)" - "") - -(define_expand "andc3" - [(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 != TImode || TARGET_POWERPC64)" - "") - -;; Power8 vector logical instructions. -(define_expand "eqv3" - [(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 != TImode || TARGET_POWERPC64)") - -;; Rewrite nand into canonical form -(define_expand "nand3" - [(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 != TImode || TARGET_POWERPC64)") - -;; The canonical form is to have the negated elment first, so we need to -;; reverse arguments. -(define_expand "orc3" - [(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 != TImode || TARGET_POWERPC64)") - ;; Vector count leading zeros (define_expand "clz2" [(set (match_operand:VEC_I 0 "register_operand" "") Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 201180) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -138,6 +138,7 @@ extern rtx rs6000_address_for_fpconvert 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: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 201180) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -30139,6 +30139,280 @@ rs6000_set_up_by_prologue (struct hard_r 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; #include "gt-rs6000.h" Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 201180) +++ gcc/config/rs6000/vsx.md (working copy) @@ -36,10 +36,6 @@ (define_mode_iterator VSX_F [V4SF V2DF]) ;; 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]) @@ -1047,370 +1043,6 @@ (define_insn "*vsx_float_fix_2" (set_attr "fp_type" "")]) -;; 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_and3_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)" - "xxland %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_and3_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)" - "@ - xxland %x0,%x1,%x2 - # - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[5] = simplify_subreg (DImode, operands[1], mode, 0); - operands[6] = simplify_subreg (DImode, operands[2], mode, 0); - operands[7] = simplify_subreg (DImode, operands[0], mode, 8); - operands[8] = simplify_subreg (DImode, operands[1], mode, 8); - operands[9] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two") - (set_attr "length" "4,8,8,8")]) - -(define_insn "*vsx_ior3_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)" - "xxlor %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_ior3_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)" - "@ - xxlor %x0,%x1,%x2 - # - # - # - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], mode)" - [(const_int 0)] -{ - operands[3] = simplify_subreg (DImode, operands[0], mode, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], 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_xor3_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) && !TARGET_POWERPC64" - "xxlxor %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_xor3_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)" - "@ - xxlxor %x0,%x1,%x2 - # - # - # - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two,three,three") - (set_attr "length" "4,8,8,8,16,16")]) - -(define_insn "*vsx_one_cmpl2_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)" - "xxlnor %x0,%x1,%x1" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_one_cmpl2_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)" - "@ - xxlnor %x0,%x1,%x1 - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[3] = simplify_subreg (DImode, operands[1], mode, 0); - operands[4] = simplify_subreg (DImode, operands[0], mode, 8); - operands[5] = simplify_subreg (DImode, operands[1], mode, 8); -} - [(set_attr "type" "vecsimple,two,two") - (set_attr "length" "4,8,8")]) - -(define_insn "*vsx_nor3_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)" - "xxlnor %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_nor3_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)" - "@ - xxlnor %x0,%x1,%x2 - # - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two") - (set_attr "length" "4,8,8,8")]) - -(define_insn "*vsx_andc3_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)" - "xxlandc %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_andc3_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)" - "@ - xxlandc %x0,%x1,%x2 - # - # - #" - "reload_completed && TARGET_POWERPC64 && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two") - (set_attr "length" "4,8,8,8")]) - -;; Power8 vector logical instructions. -(define_insn "*vsx_eqv3_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)" - "xxleqv %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_eqv3_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)" - "@ - xxleqv %x0,%x1,%x2 - # - # - #" - "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR - && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two") - (set_attr "length" "4,8,8,8")]) - -;; Rewrite nand into canonical form -(define_insn "*vsx_nand3_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)" - "xxlnand %x0,%x1,%x2" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_nand3_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)" - "@ - xxlnand %x0,%x1,%x2 - # - # - #" - "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR - && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], 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_orc3_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)" - "xxlorc %x0,%x2,%x1" - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - -(define_insn_and_split "*vsx_orc3_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)" - "@ - xxlorc %x0,%x2,%x1 - # - # - #" - "reload_completed && TARGET_POWERPC64 && TARGET_P8_VECTOR - && VECTOR_MEM_VSX_P (mode) - && int_reg_operand (operands[0], 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, 0); - operands[4] = simplify_subreg (DImode, operands[1], mode, 0); - operands[5] = simplify_subreg (DImode, operands[2], mode, 0); - operands[6] = simplify_subreg (DImode, operands[0], mode, 8); - operands[7] = simplify_subreg (DImode, operands[1], mode, 8); - operands[8] = simplify_subreg (DImode, operands[2], mode, 8); -} - [(set_attr "type" "vecsimple,two,two,two") - (set_attr "length" "4,8,8,8")]) - - ;; Permute operations ;; Build a V2DF/V2DI vector from two scalars Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 201180) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -1121,14 +1121,11 @@ enum data_align { align_abi, align_opt, #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: gcc/config/rs6000/altivec.md =================================================================== --- gcc/config/rs6000/altivec.md (revision 201180) +++ gcc/config/rs6000/altivec.md (working copy) @@ -1040,59 +1040,7 @@ (define_insn "vec_widen_smult_odd_v8hi" [(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_and3" - [(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)" - "vand %0,%1,%2" - [(set_attr "type" "vecsimple")]) - -(define_insn "*altivec_ior3" - [(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)" - "vor %0,%1,%2" - [(set_attr "type" "vecsimple")]) - -(define_insn "*altivec_xor3" - [(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)" - "vxor %0,%1,%2" - [(set_attr "type" "vecsimple")]) - -(define_insn "*altivec_one_cmpl2" - [(set (match_operand:VM 0 "register_operand" "=v") - (not:VM (match_operand:VM 1 "register_operand" "v")))] - "VECTOR_MEM_ALTIVEC_P (mode)" - "vnor %0,%1,%1" - [(set_attr "type" "vecsimple")]) - -(define_insn "*altivec_nor3" - [(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)" - "vnor %0,%1,%2" - [(set_attr "type" "vecsimple")]) - -(define_insn "*altivec_andc3" - [(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)" - "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: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 201180) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -391,6 +391,77 @@ (define_mode_attr E500_CONVERT [(SF "!TA (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")]) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -1840,7 +1911,19 @@ (define_split FAIL; }) -(define_insn "one_cmpl2" +(define_expand "one_cmpl2" + [(set (match_operand:SDI 0 "gpc_reg_operand" "") + (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))] + "" +{ + if (mode == DImode && !TARGET_POWERPC64) + { + rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX); + DONE; + } +}) + +(define_insn "*one_cmpl2" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] "" @@ -7962,10 +8045,19 @@ (define_expand "anddi3" [(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") @@ -8146,11 +8238,17 @@ (define_split (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 () @@ -8164,15 +8262,21 @@ (define_expand "iordi3" 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; @@ -8187,7 +8291,7 @@ (define_expand "xordi3" 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") @@ -8425,6 +8529,372 @@ (define_insn "*eqv3" (set_attr "length" "4")]) +;; 128-bit logical operations expanders + +(define_expand "and3" + [(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 "ior3" + [(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 "xor3" + [(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_cmpl2" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))] + "" + "") + +(define_expand "nor3" + [(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 "andc3" + [(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 "eqv3" + [(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 == TImode || mode == PTImode || TARGET_P8_VECTOR" + "") + +;; Rewrite nand into canonical form +(define_expand "nand3" + [(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 == TImode || mode == PTImode || TARGET_P8_VECTOR" + "") + +;; The canonical form is to have the negated element first, so we need to +;; reverse arguments. +(define_expand "orc3" + [(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 == TImode || mode == PTImode || TARGET_P8_VECTOR" + "") + +;; 128-bit logical operations insns and split operations +(define_insn_and_split "*and3_internal" + [(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 ""))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], mode)) + return "xxland %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], mode)) + return "vand %0,%1,%2"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], 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 "*bool3_internal" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") + (match_operator:BOOL_128 3 "boolean_or_operator" + [(match_operand:BOOL_128 1 "vlogical_operand" "%") + (match_operand:BOOL_128 2 "vlogical_operand" "")]))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], 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 "*boolc3_internal1" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") + (match_operator:BOOL_128 3 "boolean_operator" + [(not:BOOL_128 + (match_operand:BOOL_128 2 "vlogical_operand" "")) + (match_operand:BOOL_128 1 "vlogical_operand" "")]))] + "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)) + && reload_completed && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*boolc3_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 "*boolcc3_internal1" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") + (match_operator:BOOL_128 3 "boolean_operator" + [(not:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "")) + (not:BOOL_128 + (match_operand:BOOL_128 2 "vlogical_operand" ""))]))] + "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)) + && reload_completed && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*boolcc3_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 "*eqv3_internal1" + [(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" ""))))] + "TARGET_P8_VECTOR" +{ + if (vsx_register_operand (operands[0], mode)) + return "xxleqv %x0,%x1,%x2"; + + return "#"; +} + "TARGET_P8_VECTOR && reload_completed + && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*eqv3_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_cmpl3_internal" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") + (not:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "")))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], mode)) + return "xxlnor %x0,%x1,%x1"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], mode)) + return "vnor %0,%1,%1"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], 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)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + + ;; Now define ways of moving data around. ;; Set up a register with a value from the GOT table Index: gcc/testsuite/gcc.target/powerpc/bool2-p8.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool2-p8.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool2-p8.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool2-av.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool2-av.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool2-av.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool3-p7.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool3-p7.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool3-p7.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool3-p8.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool3-p8.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool3-p8.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool3-av.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool3-av.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool3-av.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool2-p5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool2-p5.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool2-p5.c (revision 0) @@ -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" Index: gcc/testsuite/gcc.target/powerpc/bool2.h =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool2.h (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool2.h (revision 0) @@ -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 */ Index: gcc/testsuite/gcc.target/powerpc/bool3.h =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool3.h (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool3.h (revision 0) @@ -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; +} Index: gcc/testsuite/gcc.target/powerpc/bool2-p7.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/bool2-p7.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/bool2-p7.c (revision 0) @@ -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"