diff options
-rw-r--r-- | gcc/config/i386/cygming.h | 9 | ||||
-rw-r--r-- | gcc/config/i386/i386.cc | 9 | ||||
-rw-r--r-- | gcc/config/riscv/bitmanip.md | 5 | ||||
-rw-r--r-- | gcc/config/riscv/iterators.md | 3 | ||||
-rw-r--r-- | gcc/config/riscv/predicates.md | 12 | ||||
-rw-r--r-- | gcc/config/riscv/riscv-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.cc | 307 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.md | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr87600.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr89313.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr120080.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/block-cmp-8.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/rvv/base/crc-builtin-zvbc.c | 66 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/xor-synthesis-1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/xor-synthesis-2.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/xor-synthesis-3.c | 8 | ||||
-rw-r--r-- | gcc/tree-switch-conversion.cc | 8 |
19 files changed, 463 insertions, 42 deletions
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index d587d25..743cc38 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -28,16 +28,15 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_SEH #define TARGET_SEH (TARGET_64BIT_MS_ABI && flag_unwind_tables) +#undef PREFERRED_STACK_BOUNDARY_DEFAULT +#define PREFERRED_STACK_BOUNDARY_DEFAULT \ + (TARGET_64BIT ? 128 : MIN_STACK_BOUNDARY) + /* Win64 with SEH cannot represent DRAP stack frames. Disable its use. Force the use of different mechanisms to allocate aligned local data. */ #undef MAX_STACK_ALIGNMENT #define MAX_STACK_ALIGNMENT (TARGET_SEH ? 128 : MAX_OFILE_ALIGNMENT) -/* 32-bit Windows aligns the stack on a 4-byte boundary but SSE instructions - may require 16-byte alignment. */ -#undef STACK_REALIGN_DEFAULT -#define STACK_REALIGN_DEFAULT (TARGET_64BIT ? 0 : 1) - /* Support hooks for SEH. */ #undef TARGET_ASM_UNWIND_EMIT #define TARGET_ASM_UNWIND_EMIT i386_pe_seh_unwind_emit diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index fd36ea8..9c24a92 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -7942,6 +7942,15 @@ ix86_update_stack_boundary (void) if (ix86_tls_descriptor_calls_expanded_in_cfun && crtl->preferred_stack_boundary < 128) crtl->preferred_stack_boundary = 128; + + /* For 32-bit MS ABI, both the incoming and preferred stack boundaries + are 32 bits, but if force_align_arg_pointer is specified, it should + prefer 128 bits for a backward-compatibility reason, which is also + what the doc suggests. */ + if (lookup_attribute ("force_align_arg_pointer", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) + && crtl->preferred_stack_boundary < 128) + crtl->preferred_stack_boundary = 128; } /* Handle the TARGET_GET_DRAP_RTX hook. Return NULL if no DRAP is diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 95df533..c226c39 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -1222,7 +1222,7 @@ we can't keep it in 64 bit variable.) then use clmul instruction to implement the CRC, otherwise (TARGET_ZBKB) generate table based using brev. */ - if ((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode) + if ((TARGET_ZBKC || TARGET_ZBC || TARGET_ZVBC) && <ANYI:MODE>mode < word_mode) expand_reversed_crc_using_clmul (<ANYI:MODE>mode, <ANYI1:MODE>mode, operands); else if (TARGET_ZBKB) @@ -1254,7 +1254,8 @@ (match_operand:SUBX 3)] UNSPEC_CRC))] /* We don't support the case when data's size is bigger than CRC's size. */ - "(TARGET_ZBKC || TARGET_ZBC) && <SUBX:MODE>mode >= <SUBX1:MODE>mode" + "(TARGET_ZBKC || TARGET_ZBC || TARGET_ZVBC) + && <SUBX:MODE>mode >= <SUBX1:MODE>mode" { /* If we have the ZBC or ZBKC extension (ie, clmul) and it is possible to store the quotient within a single variable diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index 214c20b..584b345 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -262,6 +262,9 @@ (define_code_attr fix_uns [(fix "fix") (unsigned_fix "fixuns")]) +(define_code_attr OPTAB [(ior "IOR") + (xor "XOR")]) + ;; ------------------------------------------------------------------- ;; Code Attributes diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index c9a638c..23690792 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -380,14 +380,6 @@ (and (match_code "const_int") (match_test "SINGLE_BIT_MASK_OPERAND (UINTVAL (op))"))) -;; Register, small constant or single bit constant for use in -;; bseti/binvi. -(define_predicate "arith_or_zbs_operand" - (ior (match_operand 0 "const_arith_operand") - (match_operand 0 "register_operand") - (and (match_test "TARGET_ZBS") - (match_operand 0 "single_bit_mask_operand")))) - (define_predicate "not_single_bit_mask_operand" (and (match_code "const_int") (match_test "SINGLE_BIT_MASK_OPERAND (~UINTVAL (op))"))) @@ -689,3 +681,7 @@ (define_predicate "bitpos_mask_operand" (and (match_code "const_int") (match_test "TARGET_64BIT ? INTVAL (op) == 63 : INTVAL (op) == 31"))) + +(define_predicate "reg_or_const_int_operand" + (ior (match_operand 0 "const_int_operand") + (match_operand 0 "register_operand"))) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index b0d5bbb..271a9a3 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -140,6 +140,7 @@ extern void riscv_expand_sssub (rtx, rtx, rtx); extern void riscv_expand_ustrunc (rtx, rtx); extern void riscv_expand_sstrunc (rtx, rtx); extern int riscv_register_move_cost (machine_mode, reg_class_t, reg_class_t); +extern bool synthesize_ior_xor (rtx_code, rtx [3]); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3ee88db..8b77a35 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -14035,17 +14035,53 @@ expand_crc_using_clmul (scalar_mode crc_mode, scalar_mode data_mode, rtx data = gen_rtx_ZERO_EXTEND (word_mode, operands[2]); riscv_expand_op (XOR, word_mode, a0, crc, data); - if (TARGET_64BIT) - emit_insn (gen_riscv_clmul_di (a0, a0, t0)); - else - emit_insn (gen_riscv_clmul_si (a0, a0, t0)); + if (TARGET_ZBKC || TARGET_ZBC) + { + if (TARGET_64BIT) + emit_insn (gen_riscv_clmul_di (a0, a0, t0)); + else + emit_insn (gen_riscv_clmul_si (a0, a0, t0)); - riscv_expand_op (LSHIFTRT, word_mode, a0, a0, - gen_int_mode (crc_size, word_mode)); - if (TARGET_64BIT) - emit_insn (gen_riscv_clmul_di (a0, a0, t1)); + riscv_expand_op (LSHIFTRT, word_mode, a0, a0, + gen_int_mode (crc_size, word_mode)); + if (TARGET_64BIT) + emit_insn (gen_riscv_clmul_di (a0, a0, t1)); + else + emit_insn (gen_riscv_clmul_si (a0, a0, t1)); + } else - emit_insn (gen_riscv_clmul_si (a0, a0, t1)); + { + machine_mode vmode; + if (!riscv_vector::get_vector_mode (DImode, 1).exists (&vmode)) + gcc_unreachable (); + + rtx vec = gen_reg_rtx (vmode); + + insn_code icode1 = code_for_pred_broadcast (vmode); + rtx ops1[] = {vec, a0}; + emit_nonvlmax_insn (icode1, UNARY_OP, ops1, CONST1_RTX (Pmode)); + + rtx rvv1di_reg = gen_rtx_SUBREG (RVVM1DImode, vec, 0); + insn_code icode2 = code_for_pred_vclmul_scalar (UNSPEC_VCLMUL, + E_RVVM1DImode); + rtx ops2[] = {rvv1di_reg, rvv1di_reg, t0}; + emit_nonvlmax_insn (icode2, riscv_vector::BINARY_OP, ops2, CONST1_RTX + (Pmode)); + + rtx shift_amount = gen_int_mode (data_size, Pmode); + insn_code icode3 = code_for_pred_scalar (LSHIFTRT, vmode); + rtx ops3[] = {vec, vec, shift_amount}; + emit_nonvlmax_insn (icode3, BINARY_OP, ops3, CONST1_RTX (Pmode)); + + insn_code icode4 = code_for_pred_vclmul_scalar (UNSPEC_VCLMULH, + E_RVVM1DImode); + rtx ops4[] = {rvv1di_reg, rvv1di_reg, t1}; + emit_nonvlmax_insn (icode4, riscv_vector::BINARY_OP, ops4, CONST1_RTX + (Pmode)); + + rtx vec_low_lane = gen_lowpart (DImode, vec); + riscv_emit_move (a0, vec_low_lane); + } if (crc_size > data_size) { @@ -14094,19 +14130,53 @@ expand_reversed_crc_using_clmul (scalar_mode crc_mode, scalar_mode data_mode, rtx a0 = gen_reg_rtx (word_mode); riscv_expand_op (XOR, word_mode, a0, crc, data); - if (TARGET_64BIT) - emit_insn (gen_riscv_clmul_di (a0, a0, t0)); - else - emit_insn (gen_riscv_clmul_si (a0, a0, t0)); + if (TARGET_ZBKC || TARGET_ZBC) + { + if (TARGET_64BIT) + emit_insn (gen_riscv_clmul_di (a0, a0, t0)); + else + emit_insn (gen_riscv_clmul_si (a0, a0, t0)); - rtx num_shift = gen_int_mode (GET_MODE_BITSIZE (word_mode) - data_size, - word_mode); - riscv_expand_op (ASHIFT, word_mode, a0, a0, num_shift); + rtx num_shift = gen_int_mode (BITS_PER_WORD - data_size, word_mode); + riscv_expand_op (ASHIFT, word_mode, a0, a0, num_shift); - if (TARGET_64BIT) - emit_insn (gen_riscv_clmulh_di (a0, a0, t1)); + if (TARGET_64BIT) + emit_insn (gen_riscv_clmulh_di (a0, a0, t1)); + else + emit_insn (gen_riscv_clmulh_si (a0, a0, t1)); + } else - emit_insn (gen_riscv_clmulh_si (a0, a0, t1)); + { + machine_mode vmode; + if (!riscv_vector::get_vector_mode (DImode, 1).exists (&vmode)) + gcc_unreachable (); + + rtx vec = gen_reg_rtx (vmode); + insn_code icode1 = code_for_pred_broadcast (vmode); + rtx ops1[] = {vec, a0}; + emit_nonvlmax_insn (icode1, UNARY_OP, ops1, CONST1_RTX (Pmode)); + + rtx rvv1di_reg = gen_rtx_SUBREG (RVVM1DImode, vec, 0); + insn_code icode2 = code_for_pred_vclmul_scalar (UNSPEC_VCLMUL, + E_RVVM1DImode); + rtx ops2[] = {rvv1di_reg, rvv1di_reg, t0}; + emit_nonvlmax_insn (icode2, riscv_vector::BINARY_OP, ops2, CONST1_RTX + (Pmode)); + + rtx shift_amount = gen_int_mode (BITS_PER_WORD - data_size, Pmode); + insn_code icode3 = code_for_pred_scalar (ASHIFT, vmode); + rtx ops3[] = {vec, vec, shift_amount}; + emit_nonvlmax_insn (icode3, BINARY_OP, ops3, CONST1_RTX (Pmode)); + + insn_code icode4 = code_for_pred_vclmul_scalar (UNSPEC_VCLMULH, + E_RVVM1DImode); + rtx ops4[] = {rvv1di_reg, rvv1di_reg, t1}; + emit_nonvlmax_insn (icode4, riscv_vector::BINARY_OP, ops4, CONST1_RTX + (Pmode)); + + rtx vec_low_lane = gen_lowpart (DImode, vec); + riscv_emit_move (a0, vec_low_lane); + } if (crc_size > data_size) { @@ -14140,6 +14210,205 @@ bool need_shadow_stack_push_pop_p () return is_zicfiss_p () && riscv_save_return_addr_reg_p (); } +/* Synthesize OPERANDS[0] = OPERANDS[1] CODE OPERANDS[2]. + + OPERANDS[0] and OPERANDS[1] will be a REG and may be the same + REG. + + OPERANDS[2] is a CONST_INT. + + CODE is IOR or XOR. + + Return TRUE if the operation was fully synthesized and the caller + need not generate additional code. Return FALSE if the operation + was not synthesized and the caller is responsible for emitting the + proper sequence. */ + +bool +synthesize_ior_xor (rtx_code code, rtx operands[3]) +{ + /* Trivial cases that don't need synthesis. */ + if (SMALL_OPERAND (INTVAL (operands[2])) + || ((TARGET_ZBS || TARGET_XTHEADBS || TARGET_ZBKB) + && single_bit_mask_operand (operands[2], word_mode))) + return false; + + /* The number of instructions to synthesize the constant is a good + estimate of the budget. That does not account for out of order + execution an fusion in the constant synthesis those would naturally + decrease the budget. It also does not account for the IOR/XOR at + the end of the sequence which would increase the budget. */ + int budget = (TARGET_ZBS ? riscv_const_insns (operands[2], true) : -1); + int original_budget = budget; + + /* Bits we need to set in operands[0]. As we synthesize the operation, + we clear bits in IVAL. Once IVAL is zero, then synthesis of the + operation is complete. */ + unsigned HOST_WIDE_INT ival = INTVAL (operands[2]); + + /* Check if we want to use [x]ori. Then get the remaining bits + and decrease the budget by one. */ + if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0) + { + ival &= ~HOST_WIDE_INT_UC (0x7ff); + budget--; + } + + /* Check for bseti cases. For each remaining bit in ival, + decrease the budget by one. */ + while (ival) + { + HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival); + ival &= ~tmpval; + budget--; + } + + /* If we're flipping all but a small number of bits we can pre-flip + the outliers, then flip all the bits, which would restore those + bits that were pre-flipped. */ + if ((TARGET_ZBS || TARGET_XTHEADBS || TARGET_ZBKB) + && budget < 0 + && code == XOR + && popcount_hwi (~INTVAL (operands[2])) < original_budget) + { + /* Pre-flipping bits we want to preserve. */ + rtx input = operands[1]; + ival = ~INTVAL (operands[2]); + while (ival) + { + HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival); + rtx x = GEN_INT (tmpval); + x = gen_rtx_XOR (word_mode, input, x); + emit_insn (gen_rtx_SET (operands[0], x)); + input = operands[0]; + ival &= ~tmpval; + } + + /* Now flip all the bits, which restores the bits we were + preserving. */ + rtx x = gen_rtx_NOT (word_mode, input); + emit_insn (gen_rtx_SET (operands[0], x)); + return true; + } + + /* One more approach we can try. If our budget is 3+ instructions, + then we can try to rotate the source so that the bits we want to + set are in the low 11 bits. We then use [x]ori to set those low + bits, then rotate things back into their proper place. */ + if ((TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB) + && budget < 0 + && popcount_hwi (INTVAL (operands[2])) <= 11 + && riscv_const_insns (operands[2], true) >= 3) + { + ival = INTVAL (operands[2]); + /* First see if the constant trivially fits into 11 bits in the LSB. */ + int lsb = ctz_hwi (ival); + int msb = BITS_PER_WORD - 1 - clz_hwi (ival); + if (msb - lsb + 1 <= 11) + { + /* Rotate the source right by LSB bits. */ + rtx x = GEN_INT (lsb); + x = gen_rtx_ROTATERT (word_mode, operands[1], x); + emit_insn (gen_rtx_SET (operands[0], x)); + + /* Shift the constant right by LSB bits. */ + x = GEN_INT (ival >> lsb); + + /* Perform the IOR/XOR operation. */ + x = gen_rtx_fmt_ee (code, word_mode, operands[0], x); + emit_insn (gen_rtx_SET (operands[0], x)); + + /* And rotate left to put everything back in place, we don't + have rotate left by a constant, so use rotate right by + an adjusted constant. */ + x = GEN_INT (BITS_PER_WORD - lsb); + x = gen_rtx_ROTATERT (word_mode, operands[1], x); + emit_insn (gen_rtx_SET (operands[0], x)); + return true; + } + + /* Maybe the bits are split between the high and low parts + of the constant. A bit more complex, but still manageable. + + Conceptually we want to rotate left the constant by the number + of leading zeros after masking off all but the low 11 bits. */ + int rotcount = clz_hwi (ival & 0x7ff) - (BITS_PER_WORD - 11); + + /* Rotate the constant left by MSB bits. */ + ival = (ival << rotcount) | (ival >> (BITS_PER_WORD - rotcount)); + + /* Now we can do the same tests as before. */ + lsb = ctz_hwi (ival); + msb = BITS_PER_WORD - clz_hwi (ival); + if ((INTVAL (operands[2]) & HOST_WIDE_INT_UC (0x7ff)) != 0 + && msb - lsb + 1 <= 11) + { + /* Rotate the source left by ROTCOUNT bits, we don't have + rotate left by a constant, so use rotate right by an + adjusted constant. */ + rtx x = GEN_INT (BITS_PER_WORD - rotcount); + x = gen_rtx_ROTATERT (word_mode, operands[1], x); + emit_insn (gen_rtx_SET (operands[0], x)); + + /* We've already rotated the constant. So perform the IOR/XOR + operation. */ + x = GEN_INT (ival); + x = gen_rtx_fmt_ee (code, word_mode, operands[0], x); + emit_insn (gen_rtx_SET (operands[0], x)); + + /* And rotate right to put everything into its proper place. */ + x = GEN_INT (rotcount); + x = gen_rtx_ROTATERT (word_mode, operands[0], x); + emit_insn (gen_rtx_SET (operands[0], x)); + return true; + } + } + + /* If after accounting for bseti the remaining budget has + gone to less than zero, it forces the value into a + register and performs the IOR operation. It returns + TRUE to the caller so the caller knows code generation + is complete. */ + if (budget < 0) + { + rtx x = force_reg (word_mode, operands[2]); + x = gen_rtx_fmt_ee (code, word_mode, operands[1], x); + emit_insn (gen_rtx_SET (operands[0], x)); + return true; + } + + /* Synthesis is better than loading the constant. */ + ival = INTVAL (operands[2]); + rtx input = operands[1]; + + /* Emit the [x]ori insn that sets the low 11 bits into + the proper state. */ + if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0) + { + rtx x = GEN_INT (ival & HOST_WIDE_INT_UC (0x7ff)); + x = gen_rtx_fmt_ee (code, word_mode, input, x); + emit_insn (gen_rtx_SET (operands[0], x)); + input = operands[0]; + ival &= ~HOST_WIDE_INT_UC (0x7ff); + } + + /* We figure out a single bit as a constant and + generate a CONST_INT node for that. Then we + construct the IOR node, then the SET node and + emit it. An IOR with a suitable constant that is + a single bit will be implemented with a bseti. */ + while (ival) + { + HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival); + rtx x = GEN_INT (tmpval); + x = gen_rtx_fmt_ee (code, word_mode, input, x); + emit_insn (gen_rtx_SET (operands[0], x)); + input = operands[0]; + ival &= ~tmpval; + } + return true; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 259997f..154b49d 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1767,8 +1767,15 @@ (define_expand "<optab><mode>3" [(set (match_operand:X 0 "register_operand") (any_or:X (match_operand:X 1 "register_operand" "") - (match_operand:X 2 "arith_or_zbs_operand" "")))] - "") + (match_operand:X 2 "reg_or_const_int_operand" "")))] + "" + +{ + /* If synthesis of the logical op is successful, then no further code + generation is necessary. Else just generate code normally. */ + if (CONST_INT_P (operands[2]) && synthesize_ior_xor (<OPTAB>, operands)) + DONE; +}) (define_insn "*<optab><mode>3" [(set (match_operand:X 0 "register_operand" "=r,r") diff --git a/gcc/testsuite/gcc.dg/pr87600.h b/gcc/testsuite/gcc.dg/pr87600.h index af91f63..c89071eb 100644 --- a/gcc/testsuite/gcc.dg/pr87600.h +++ b/gcc/testsuite/gcc.dg/pr87600.h @@ -7,7 +7,7 @@ #elif defined (__i386__) # define REG1 "%eax" # define REG2 "%edx" -#elif defined (__powerpc__) || defined (__POWERPC__) +#elif defined (__powerpc__) || defined (__POWERPC__) || defined (__PPC__) # define REG1 "r3" # define REG2 "r4" #elif defined (__s390__) diff --git a/gcc/testsuite/gcc.dg/pr89313.c b/gcc/testsuite/gcc.dg/pr89313.c index 76cb091..7de64da 100644 --- a/gcc/testsuite/gcc.dg/pr89313.c +++ b/gcc/testsuite/gcc.dg/pr89313.c @@ -8,7 +8,7 @@ # define REG "r0" #elif defined (__i386__) # define REG "%eax" -#elif defined (__powerpc__) || defined (__POWERPC__) +#elif defined (__powerpc__) || defined (__POWERPC__) || defined (__PPC__) # define REG "r3" #elif defined (__s390__) # define REG "0" diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr120080.c b/gcc/testsuite/gcc.dg/tree-ssa/pr120080.c new file mode 100644 index 0000000..d71ef5e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr120080.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -O2" } */ + +void __GIMPLE (ssa,startwith("switchlower1")) +foo (int b) +{ + __BB(2): + switch (b) {default: L9; case 0: L5; case 5: L5; case 101: L5; } + + __BB(3): +L9: + switch (b) {default: L7; case 5: L6; case 101: L6; } + + __BB(4): +L6: + __builtin_unreachable (); + + __BB(5): +L7: + __builtin_trap (); + + __BB(6): +L5: + return; + +} diff --git a/gcc/testsuite/gcc.target/powerpc/block-cmp-8.c b/gcc/testsuite/gcc.target/powerpc/block-cmp-8.c index 22a48c8..0f35ddd 100644 --- a/gcc/testsuite/gcc.target/powerpc/block-cmp-8.c +++ b/gcc/testsuite/gcc.target/powerpc/block-cmp-8.c @@ -1,6 +1,6 @@ /* { dg-do run { target ilp32 } } */ /* { dg-options "-O2 -mpowerpc64" } */ -/* { dg-require-effective-target has_arch_ppc64 } */ +/* { dg-require-effective-target powerpc64 } */ /* { dg-timeout-factor 2 } */ /* Verify memcmp on m32 mpowerpc64 */ diff --git a/gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c b/gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c new file mode 100644 index 0000000..04644cd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gb -mabi=lp64d" } */ + +unsigned long foo(unsigned long src) { return src | 0x8c00000000000001; } + +/* { dg-final { scan-assembler-times "\\srori\t" 2 } } */ +/* { dg-final { scan-assembler-times "\\sori\t" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c b/gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c new file mode 100644 index 0000000..f28fe5e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gb -mabi=lp64d" } */ + +unsigned long foo(unsigned long src) { return src | 0x8800000000000007; } + +/* { dg-final { scan-assembler-times "\\sbseti\t" 2 } } */ +/* { dg-final { scan-assembler-times "\\sori\t" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/crc-builtin-zvbc.c b/gcc/testsuite/gcc.target/riscv/rvv/base/crc-builtin-zvbc.c new file mode 100644 index 0000000..2d5fa88 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/crc-builtin-zvbc.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvbc -mabi=lp64d" } */ + +#include <stdint-gcc.h> + +int8_t crc8_data8 () +{ + return __builtin_crc8_data8 (0x34, 'a', 0x12); +} + +int16_t crc16_data8 () +{ + return __builtin_crc16_data8 (0x1234, 'a', 0x1021); +} + +int16_t crc16_data16 () +{ + return __builtin_crc16_data16 (0x1234, 0x3214, 0x1021); +} + +int32_t crc32_data8 () +{ + return __builtin_crc32_data8 (0xffffffff, 0x32, 0x4002123); +} + +int32_t crc32_data16 () +{ + return __builtin_crc32_data16 (0xffffffff, 0x3232, 0x4002123); +} + +int32_t crc32_data32 () +{ + return __builtin_crc32_data32 (0xffffffff, 0x123546ff, 0x4002123); +} + +int8_t rev_crc8_data8 () +{ + return __builtin_rev_crc8_data8 (0x34, 'a', 0x12); +} + +int16_t rev_crc16_data8 () +{ + return __builtin_rev_crc16_data8 (0x1234, 'a', 0x1021); +} + +int16_t rev_crc16_data16 () +{ + return __builtin_rev_crc16_data16 (0x1234, 0x3214, 0x1021); +} + +int32_t rev_crc32_data8 () +{ + return __builtin_rev_crc32_data8 (0xffffffff, 0x32, 0x4002123); +} + +int32_t rev_crc32_data16 () +{ + return __builtin_rev_crc32_data16 (0xffffffff, 0x3232, 0x4002123); +} + +int32_t rev_crc32_data32 () +{ + return __builtin_rev_crc32_data32 (0xffffffff, 0x123546ff, 0x4002123); +} +/* { dg-final { scan-assembler-times "vclmul.vx" 12 } } */ +/* { dg-final { scan-assembler-times "vclmulh.vx" 12 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/xor-synthesis-1.c b/gcc/testsuite/gcc.target/riscv/xor-synthesis-1.c new file mode 100644 index 0000000..c630a79 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xor-synthesis-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gb -mabi=lp64d" } */ + +unsigned long foo(unsigned long src) { return src ^ 0xffffffffefffffffUL; } + +/* { dg-final { scan-assembler-times "\\sbinvi\t" 1 } } */ +/* { dg-final { scan-assembler-times "\\snot\t" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/xor-synthesis-2.c b/gcc/testsuite/gcc.target/riscv/xor-synthesis-2.c new file mode 100644 index 0000000..25457d2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xor-synthesis-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gb -mabi=lp64d" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ + +unsigned long foo(unsigned long src) { return src ^ 0x8800000000000007; } + +/* xfailed until we remove mvconst_internal. */ +/* { dg-final { scan-assembler-times "\\sbinvi\t" 2 { xfail *-*-* } } } */ +/* { dg-final { scan-assembler-times "\\sxori\t" 1 { xfail *-*-* } } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/xor-synthesis-3.c b/gcc/testsuite/gcc.target/riscv/xor-synthesis-3.c new file mode 100644 index 0000000..765904b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xor-synthesis-3.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gb -mabi=lp64d" } */ + +unsigned long foo(unsigned long src) { return src ^ 0x8c00000000000001; } + +/* { dg-final { scan-assembler-times "\\srori\t" 2 } } */ +/* { dg-final { scan-assembler-times "\\sxori\t" 1 } } */ + diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc index dea217a..bd4de96 100644 --- a/gcc/tree-switch-conversion.cc +++ b/gcc/tree-switch-conversion.cc @@ -1793,12 +1793,14 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters, int max_c) end up with as few clusters as possible. */ unsigned l = clusters.length (); - auto_vec<min_cluster_item> min; - min.reserve (l + 1); - gcc_checking_assert (l > 0); + if (l == 0) + return clusters.copy (); gcc_checking_assert (l <= INT_MAX); + auto_vec<min_cluster_item> min; + min.reserve (l + 1); + int bits_in_word = GET_MODE_BITSIZE (word_mode); /* First phase: Compute the minimum number of clusters for each prefix of the |