Hello! Attached patch moves a pack of duplicated code from i386.md to i386.c.
No functional change. 2012-10-18 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (rdpmc): Remove expander. (rdtsc): Ditto. (rdtscp): Ditto. (rdpmc): Rename from *rdpmc. (rdpmc_rex64): Rename from *rdpmc_rex64. (rdtsc): Rename from *rdtsc. (rdtsc_rex64): Rename from *rdtsc_rex64. (rdtscp): Rename from *rdtscp. (rdtscp_rex64): Rename from *rdtscp_rex64. * config/i386/i386.c (struct builtin_description bdesc_special_args) <IX86_BUILTIN_RDTSC>: Use CODE_FOR_NOTHING. <IX86_BUILTIN_RDTSCP>: Ditto. (struct builtin_description bdesc__args) <IX86_BUILTIN_RDPMC>: Ditto. (ix86_expand_builtin) <IX86_BUILTIN_{RDPMC,RDTSC,RDTSCP}>: Handle here. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 192575) +++ config/i386/i386.c (working copy) @@ -26768,8 +26768,8 @@ static const struct builtin_description bdesc_pcmp /* Special builtins with variable number of arguments. */ static const struct builtin_description bdesc_special_args[] = { - { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rdtsc, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, UNKNOWN, (int) UINT64_FTYPE_VOID }, - { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rdtscp, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED }, + { ~OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, UNKNOWN, (int) UINT64_FTYPE_VOID }, + { ~OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED }, { ~OPTION_MASK_ISA_64BIT, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID }, /* MMX */ @@ -26887,7 +26887,7 @@ static const struct builtin_description bdesc_args { { ~OPTION_MASK_ISA_64BIT, CODE_FOR_bsr, "__builtin_ia32_bsrsi", IX86_BUILTIN_BSRSI, UNKNOWN, (int) INT_FTYPE_INT }, { OPTION_MASK_ISA_64BIT, CODE_FOR_bsr_rex64, "__builtin_ia32_bsrdi", IX86_BUILTIN_BSRDI, UNKNOWN, (int) INT64_FTYPE_INT64 }, - { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rdpmc, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT }, + { ~OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT }, { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rotlqi3, "__builtin_ia32_rolqi", IX86_BUILTIN_ROLQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT }, { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rotlhi3, "__builtin_ia32_rolhi", IX86_BUILTIN_ROLHI, UNKNOWN, (int) UINT16_FTYPE_UINT16_INT }, { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rotrqi3, "__builtin_ia32_rorqi", IX86_BUILTIN_RORQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT }, @@ -30452,7 +30452,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub enum insn_code icode; tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg0, arg1, arg2, arg3, arg4; - rtx op0, op1, op2, op3, op4, pat; + rtx op0, op1, op2, op3, op4, pat, insn; enum machine_mode mode0, mode1, mode2, mode3, mode4; unsigned int fcode = DECL_FUNCTION_CODE (fndecl); @@ -30633,6 +30633,65 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub return target; } + case IX86_BUILTIN_RDPMC: + case IX86_BUILTIN_RDTSC: + case IX86_BUILTIN_RDTSCP: + + op0 = gen_reg_rtx (DImode); + op1 = gen_reg_rtx (DImode); + + if (fcode == IX86_BUILTIN_RDPMC) + { + arg0 = CALL_EXPR_ARG (exp, 0); + op2 = expand_normal (arg0); + if (!register_operand (op2, SImode)) + op2 = copy_to_mode_reg (SImode, op2); + + insn = (TARGET_64BIT + ? gen_rdpmc_rex64 (op0, op1, op2) + : gen_rdpmc (op0, op2)); + emit_insn (insn); + } + else if (fcode == IX86_BUILTIN_RDTSC) + { + insn = (TARGET_64BIT + ? gen_rdtsc_rex64 (op0, op1) + : gen_rdtsc (op0)); + emit_insn (insn); + } + else + { + op2 = gen_reg_rtx (SImode); + + insn = (TARGET_64BIT + ? gen_rdtscp_rex64 (op0, op1, op2) + : gen_rdtscp (op0, op2)); + emit_insn (insn); + + arg0 = CALL_EXPR_ARG (exp, 0); + op4 = expand_normal (arg0); + if (!address_operand (op4, VOIDmode)) + { + op4 = convert_memory_address (Pmode, op4); + op4 = copy_addr_to_reg (op4); + } + emit_move_insn (gen_rtx_MEM (SImode, op4), op2); + } + + if (target == 0) + target = gen_reg_rtx (mode); + + if (TARGET_64BIT) + { + op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32), + op1, 1, OPTAB_DIRECT); + op0 = expand_simple_binop (DImode, IOR, op0, op1, + op0, 1, OPTAB_DIRECT); + } + + emit_move_insn (target, op0); + return target; + case IX86_BUILTIN_LLWPCB: arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 192575) +++ config/i386/i386.md (working copy) @@ -17975,40 +17975,7 @@ (set_attr "prefix_extra" "1") (set_attr "mode" "DI")]) -(define_expand "rdpmc" - [(match_operand:DI 0 "register_operand") - (match_operand:SI 1 "register_operand")] - "" -{ - rtx reg = gen_reg_rtx (DImode); - rtx si; - - si = gen_rtx_UNSPEC_VOLATILE (DImode, gen_rtvec (1, operands[1]), - UNSPECV_RDPMC); - - if (TARGET_64BIT) - { - rtvec vec = rtvec_alloc (2); - rtx load = gen_rtx_PARALLEL (VOIDmode, vec); - rtx upper = gen_reg_rtx (DImode); - rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, - gen_rtvec (1, const0_rtx), - UNSPECV_RDPMC); - RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, si); - RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); - emit_insn (load); - upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), - NULL, 1, OPTAB_DIRECT); - reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, - OPTAB_DIRECT); - } - else - emit_insn (gen_rtx_SET (VOIDmode, reg, si)); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); - DONE; -}) - -(define_insn "*rdpmc" +(define_insn "rdpmc" [(set (match_operand:DI 0 "register_operand" "=A") (unspec_volatile:DI [(match_operand:SI 1 "register_operand" "c")] UNSPECV_RDPMC))] @@ -18017,44 +17984,18 @@ [(set_attr "type" "other") (set_attr "length" "2")]) -(define_insn "*rdpmc_rex64" +(define_insn "rdpmc_rex64" [(set (match_operand:DI 0 "register_operand" "=a") (unspec_volatile:DI [(match_operand:SI 2 "register_operand" "c")] UNSPECV_RDPMC)) - (set (match_operand:DI 1 "register_operand" "=d") - (unspec_volatile:DI [(const_int 0)] UNSPECV_RDPMC))] + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(match_dup 2)] UNSPECV_RDPMC))] "TARGET_64BIT" "rdpmc" [(set_attr "type" "other") (set_attr "length" "2")]) -(define_expand "rdtsc" - [(set (match_operand:DI 0 "register_operand") - (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] - "" -{ - if (TARGET_64BIT) - { - rtvec vec = rtvec_alloc (2); - rtx load = gen_rtx_PARALLEL (VOIDmode, vec); - rtx upper = gen_reg_rtx (DImode); - rtx lower = gen_reg_rtx (DImode); - rtx src = gen_rtx_UNSPEC_VOLATILE (DImode, - gen_rtvec (1, const0_rtx), - UNSPECV_RDTSC); - RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, lower, src); - RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, src); - emit_insn (load); - upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), - NULL, 1, OPTAB_DIRECT); - lower = expand_simple_binop (DImode, IOR, lower, upper, lower, 1, - OPTAB_DIRECT); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], lower)); - DONE; - } -}) - -(define_insn "*rdtsc" +(define_insn "rdtsc" [(set (match_operand:DI 0 "register_operand" "=A") (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] "!TARGET_64BIT" @@ -18062,7 +18003,7 @@ [(set_attr "type" "other") (set_attr "length" "2")]) -(define_insn "*rdtsc_rex64" +(define_insn "rdtsc_rex64" [(set (match_operand:DI 0 "register_operand" "=a") (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC)) (set (match_operand:DI 1 "register_operand" "=d") @@ -18072,48 +18013,7 @@ [(set_attr "type" "other") (set_attr "length" "2")]) -(define_expand "rdtscp" - [(match_operand:DI 0 "register_operand") - (match_operand:SI 1 "memory_operand")] - "" -{ - rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, - gen_rtvec (1, const0_rtx), - UNSPECV_RDTSCP); - rtx si = gen_rtx_UNSPEC_VOLATILE (SImode, - gen_rtvec (1, const0_rtx), - UNSPECV_RDTSCP); - rtx reg = gen_reg_rtx (DImode); - rtx tmp = gen_reg_rtx (SImode); - - if (TARGET_64BIT) - { - rtvec vec = rtvec_alloc (3); - rtx load = gen_rtx_PARALLEL (VOIDmode, vec); - rtx upper = gen_reg_rtx (DImode); - RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); - RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); - RTVEC_ELT (vec, 2) = gen_rtx_SET (VOIDmode, tmp, si); - emit_insn (load); - upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), - NULL, 1, OPTAB_DIRECT); - reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, - OPTAB_DIRECT); - } - else - { - rtvec vec = rtvec_alloc (2); - rtx load = gen_rtx_PARALLEL (VOIDmode, vec); - RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); - RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, tmp, si); - emit_insn (load); - } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); - emit_insn (gen_rtx_SET (VOIDmode, operands[1], tmp)); - DONE; -}) - -(define_insn "*rdtscp" +(define_insn "rdtscp" [(set (match_operand:DI 0 "register_operand" "=A") (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) (set (match_operand:SI 1 "register_operand" "=c") @@ -18123,11 +18023,11 @@ [(set_attr "type" "other") (set_attr "length" "3")]) -(define_insn "*rdtscp_rex64" +(define_insn "rdtscp_rex64" [(set (match_operand:DI 0 "register_operand" "=a") (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) (set (match_operand:DI 1 "register_operand" "=d") - (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) (set (match_operand:SI 2 "register_operand" "=c") (unspec_volatile:SI [(const_int 0)] UNSPECV_RDTSCP))] "TARGET_64BIT"