Hello! Attached patch switches x86 to TARGET_SUPPORTS_WIDE_INT.
The patch builds on the fact that build requires HOST_BITS_PER_WIDE_INT = 64 capable host. Taking this in account, noticeable blocks of code can be removed, and all but one immed_double_const can be removed. The only wide-int mode that remains is TImode. 2015-04-30 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.h (TARGET_SUPPORTS_WIDE_INT): New define. * config/i386/i386.c (ix86_legitimate_constant_p): Handle TImode as CONST_WIDE_INT, not CONST_DOUBLE. (ix86_cannot_force_const_mem): Handle CONST_WIDE_INT. (output_pic_addr_const): Do not handle VOIDmode CONST_DOUBLEs. (ix86_find_base_term): Do not check for CONST_DOUBLE. (ix86_print_operand): Do not handle non-FPmode CONST_DOUBLEs. (ix86_build_signbit_mask): Rewrite using wide ints. (ix86_split_to_parts) [HOST_BITS_PER_WIDE_INT < 64]: Remove. (ix86_rtx_costs): Handle CONST_WIDE_INT. (find_constant): Ditto. * config/i386/i386.md (bts, btr, btc peepholes): Rewrite using gen_int_mode. * config/i386/predicates.md (x86_64_immediate_operand) <case CONST_INT>: Remove HOST_BITS_PER_WIDE_INT == 32 code. (x86_64_zext_immediate_operand): Remove CONST_DOUBLE handling. <case CONST_INT>: Remove HOST_BITS_PER_WIDE_INT == 32 code. (const0_operand): Also match const_wide_int. (constm1_operand): Ditto. (const1_operand): Ditto. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32} and i686-linux-gnu. I won't be able to commit the patch until Monday. H.J., can you please test it on your SPEC testers, so there won't be any surprises w.r.t. performance issues. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 222610) +++ config/i386/i386.c (working copy) @@ -13075,7 +13075,7 @@ ix86_legitimate_constant_p (machine_mode, rtx x) #endif break; - case CONST_DOUBLE: + case CONST_WIDE_INT: if (GET_MODE (x) == TImode && x != CONST0_RTX (TImode) && !TARGET_64BIT) @@ -13105,6 +13105,7 @@ ix86_cannot_force_const_mem (machine_mode mode, rt switch (GET_CODE (x)) { case CONST_INT: + case CONST_WIDE_INT: case CONST_DOUBLE: case CONST_VECTOR: return false; @@ -13131,7 +13132,7 @@ is_imported_p (rtx x) /* Nonzero if the constant value X is a legitimate general operand when generating PIC code. It is given that flag_pic is on and - that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + that X satisfies CONSTANT_P. */ bool legitimate_pic_operand_p (rtx x) @@ -14587,20 +14588,9 @@ output_pic_addr_const (FILE *file, rtx x, int code break; case CONST_DOUBLE: - if (GET_MODE (x) == VOIDmode) - { - /* We can use %d if the number is <32 bits and positive. */ - if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) - fprintf (file, "0x%lx%08lx", - (unsigned long) CONST_DOUBLE_HIGH (x), - (unsigned long) CONST_DOUBLE_LOW (x)); - else - fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); - } - else - /* We can't handle floating point constants; - TARGET_PRINT_OPERAND must handle them. */ - output_operand_lossage ("floating constant misused"); + /* We can't handle floating point constants; + TARGET_PRINT_OPERAND must handle them. */ + output_operand_lossage ("floating constant misused"); break; case PLUS: @@ -14960,8 +14950,7 @@ ix86_find_base_term (rtx x) return x; term = XEXP (x, 0); if (GET_CODE (term) == PLUS - && (CONST_INT_P (XEXP (term, 1)) - || GET_CODE (XEXP (term, 1)) == CONST_DOUBLE)) + && CONST_INT_P (XEXP (term, 1))) term = XEXP (term, 0); if (GET_CODE (term) != UNSPEC || (XINT (term, 1) != UNSPEC_GOTPCREL @@ -15965,7 +15954,7 @@ ix86_print_operand (FILE *file, rtx x, int code) if (code != 'P' && code != 'p') { - if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE) + if (CONST_INT_P (x)) { if (ASSEMBLER_DIALECT == ASM_ATT) putc ('$', file); @@ -19442,12 +19431,9 @@ rtx ix86_build_signbit_mask (machine_mode mode, bool vect, bool invert) { machine_mode vec_mode, imode; - HOST_WIDE_INT hi, lo; - int shift = 63; - rtx v; - rtx mask; + wide_int w; + rtx mask, v; - /* Find the sign bit, sign extended to 2*HWI. */ switch (mode) { case V16SImode: @@ -19459,7 +19445,6 @@ ix86_build_signbit_mask (machine_mode mode, bool v vec_mode = mode; mode = GET_MODE_INNER (mode); imode = SImode; - lo = 0x80000000, hi = lo < 0; break; case V8DImode: @@ -19471,54 +19456,25 @@ ix86_build_signbit_mask (machine_mode mode, bool v vec_mode = mode; mode = GET_MODE_INNER (mode); imode = DImode; - if (HOST_BITS_PER_WIDE_INT >= 64) - lo = (HOST_WIDE_INT)1 << shift, hi = -1; - else - lo = 0, hi = (HOST_WIDE_INT)1 << (shift - HOST_BITS_PER_WIDE_INT); break; case TImode: case TFmode: vec_mode = VOIDmode; - if (HOST_BITS_PER_WIDE_INT >= 64) - { - imode = TImode; - lo = 0, hi = (HOST_WIDE_INT)1 << shift; - } - else - { - rtvec vec; + imode = TImode; + break; - imode = DImode; - lo = 0, hi = (HOST_WIDE_INT)1 << (shift - HOST_BITS_PER_WIDE_INT); - - if (invert) - { - lo = ~lo, hi = ~hi; - v = constm1_rtx; - } - else - v = const0_rtx; - - mask = immed_double_const (lo, hi, imode); - - vec = gen_rtvec (2, v, mask); - v = gen_rtx_CONST_VECTOR (V2DImode, vec); - v = copy_to_mode_reg (mode, gen_lowpart (mode, v)); - - return v; - } - break; - default: gcc_unreachable (); } + w = wi::set_bit_in_zero (GET_MODE_BITSIZE (mode) - 1, + GET_MODE_BITSIZE (mode)); if (invert) - lo = ~lo, hi = ~hi; + w = wi::bit_not (w); /* Force this value into the low part of a fp vector constant. */ - mask = immed_double_const (lo, hi, imode); + mask = immed_wide_int_const (w, imode); mask = gen_lowpart (mode, mask); if (vec_mode == VOIDmode) @@ -22734,25 +22690,20 @@ ix86_split_to_parts (rtx operand, rtx *parts, mach real_to_target (l, &r, mode); /* Do not use shift by 32 to avoid warning on 32bit systems. */ - if (HOST_BITS_PER_WIDE_INT >= 64) - parts[0] - = gen_int_mode - ((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1)) - + ((((HOST_WIDE_INT) l[1]) << 31) << 1), - DImode); - else - parts[0] = immed_double_const (l[0], l[1], DImode); + parts[0] + = gen_int_mode + ((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1)) + + ((((HOST_WIDE_INT) l[1]) << 31) << 1), + DImode); if (upper_mode == SImode) parts[1] = gen_int_mode (l[2], SImode); - else if (HOST_BITS_PER_WIDE_INT >= 64) + else parts[1] = gen_int_mode ((l[2] & (((HOST_WIDE_INT) 2 << 31) - 1)) + ((((HOST_WIDE_INT) l[3]) << 31) << 1), DImode); - else - parts[1] = immed_double_const (l[2], l[3], DImode); } else gcc_unreachable (); @@ -42019,12 +41970,11 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_ *total = 0; return true; + case CONST_WIDE_INT: + *total = 0; + return true; + case CONST_DOUBLE: - if (mode == VOIDmode) - { - *total = 0; - return true; - } switch (standard_80387_constant_p (x)) { case 1: /* 0.0 */ @@ -50652,6 +50602,7 @@ find_constant (rtx in_rtx, imm_info *imm_values) break; case CONST_DOUBLE: + case CONST_WIDE_INT: (imm_values->imm)++; (imm_values->imm64)++; break; Index: config/i386/i386.h =================================================================== --- config/i386/i386.h (revision 222610) +++ config/i386/i386.h (working copy) @@ -2563,6 +2563,8 @@ extern void debug_dispatch_window (int); /* For switching between functions with different target attributes. */ #define SWITCHABLE_TARGET 1 +#define TARGET_SUPPORTS_WIDE_INT 1 + /* Local variables: version-control: t Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 222610) +++ config/i386/i386.md (working copy) @@ -10686,17 +10686,10 @@ "TARGET_64BIT && !TARGET_USE_BT" [(const_int 0)] { - HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; - rtx op1; + int i = INTVAL (operands[1]); - if (HOST_BITS_PER_WIDE_INT >= 64) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else if (i < HOST_BITS_PER_WIDE_INT) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else - lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); + rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); - op1 = immed_double_const (lo, hi, DImode); if (i >= 31) { emit_move_insn (operands[2], op1); @@ -10718,17 +10711,10 @@ "TARGET_64BIT && !TARGET_USE_BT" [(const_int 0)] { - HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; - rtx op1; + int i = INTVAL (operands[1]); - if (HOST_BITS_PER_WIDE_INT >= 64) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else if (i < HOST_BITS_PER_WIDE_INT) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else - lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); - - op1 = immed_double_const (~lo, ~hi, DImode); + rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); + if (i >= 32) { emit_move_insn (operands[2], op1); @@ -10751,17 +10737,10 @@ "TARGET_64BIT && !TARGET_USE_BT" [(const_int 0)] { - HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; - rtx op1; + int i = INTVAL (operands[1]); - if (HOST_BITS_PER_WIDE_INT >= 64) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else if (i < HOST_BITS_PER_WIDE_INT) - lo = (HOST_WIDE_INT)1 << i, hi = 0; - else - lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); + rtx op1 = gen_int_mode (HOST_WIDE_INT_1U << i, DImode); - op1 = immed_double_const (lo, hi, DImode); if (i >= 31) { emit_move_insn (operands[2], op1); Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 222610) +++ config/i386/predicates.md (working copy) @@ -135,18 +135,10 @@ switch (GET_CODE (op)) { case CONST_INT: - /* CONST_DOUBLES never match, since HOST_BITS_PER_WIDE_INT is known - to be at least 32 and this all acceptable constants are - represented as CONST_INT. */ - if (HOST_BITS_PER_WIDE_INT == 32) - return true; - else - { - HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (op), DImode); - return trunc_int_for_mode (val, SImode) == val; - } - break; - + { + HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (op), DImode); + return trunc_int_for_mode (val, SImode) == val; + } case SYMBOL_REF: /* For certain code models, the symbolic references are known to fit. in CM_SMALL_PIC model we know it fits if it is local to the shared @@ -253,21 +245,12 @@ ;; Return true if VALUE can be stored in the zero extended immediate field. (define_predicate "x86_64_zext_immediate_operand" - (match_code "const_double,const_int,symbol_ref,label_ref,const") + (match_code "const_int,symbol_ref,label_ref,const") { switch (GET_CODE (op)) { - case CONST_DOUBLE: - if (HOST_BITS_PER_WIDE_INT == 32) - return (GET_MODE (op) == VOIDmode && !CONST_DOUBLE_HIGH (op)); - else - return false; - case CONST_INT: - if (HOST_BITS_PER_WIDE_INT == 32) - return INTVAL (op) >= 0; - else - return !(INTVAL (op) & ~(HOST_WIDE_INT) 0xffffffff); + return !(INTVAL (op) & ~(HOST_WIDE_INT) 0xffffffff); case SYMBOL_REF: /* For certain code models, the symbolic references are known to fit. */ @@ -625,7 +608,7 @@ ;; Match exactly zero. (define_predicate "const0_operand" - (match_code "const_int,const_double,const_vector") + (match_code "const_int,const_wide_int,const_double,const_vector") { if (mode == VOIDmode) mode = GET_MODE (op); @@ -634,7 +617,7 @@ ;; Match -1. (define_predicate "constm1_operand" - (match_code "const_int,const_double,const_vector") + (match_code "const_int,const_wide_int,const_double,const_vector") { if (mode == VOIDmode) mode = GET_MODE (op); @@ -643,7 +626,7 @@ ;; Match one or vector filled with ones. (define_predicate "const1_operand" - (match_code "const_int,const_double,const_vector") + (match_code "const_int,const_wide_int,const_double,const_vector") { if (mode == VOIDmode) mode = GET_MODE (op);