From patchwork Mon Sep 6 06:48:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 63876 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 124BCB70F7 for ; Mon, 6 Sep 2010 16:49:30 +1000 (EST) Received: (qmail 16426 invoked by alias); 6 Sep 2010 06:49:28 -0000 Received: (qmail 16416 invoked by uid 22791); 6 Sep 2010 06:49:26 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, TW_ZJ, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-qy0-f182.google.com (HELO mail-qy0-f182.google.com) (209.85.216.182) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 06 Sep 2010 06:49:01 +0000 Received: by qyk4 with SMTP id 4so4334623qyk.20 for ; Sun, 05 Sep 2010 23:48:59 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.105.4 with SMTP id r4mr269088qao.83.1283755739033; Sun, 05 Sep 2010 23:48:59 -0700 (PDT) Received: by 10.229.28.200 with HTTP; Sun, 5 Sep 2010 23:48:58 -0700 (PDT) Date: Mon, 6 Sep 2010 08:48:58 +0200 Message-ID: Subject: [PATCH, i386]: Macroize stack_protect_* patterns From: Uros Bizjak To: gcc-patches@gcc.gnu.org Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello! Fairly trivial macroization. A new operand modifier '%@' was introduced to handle thread pointer load segment register specialization for CM_KERNEL code model. 2010-09-06 Uros Bizjak * config/i386/i386.md (iptrsize): New mode attribute. (tp_seg): Ditto. (*load_tp_): Macroize insn from *load_tp_{si,di} using P mode iterator. (*add_tp_): Ditto from *add_tp_{si,di}. (stack_protect_set_): Ditto from stack_protect_set_{si,di}. (stack_protect_test_): Ditto from stack_protect_test_{si,di}. (stack_tls_protect_set_): Ditto from stack_tls_protect_set_{si,di}. Use %@ to output segment register of thread base pointer load. (stack_tls_protect_test_): Ditto from stack_tls_protect_test_{si,di}. Use %@ to output segment register of thread base pointer load. (stack_protect_set): Rewrite using indirect functions. (stack_protect_test): Ditto. * config/i386/i386.c (ix86_print_operand_punct_valid): Add '@'. (ix86_print_operand): Handle '@'. Tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline. Uros. Index: i386/i386.md =================================================================== --- i386/i386.md (revision 163879) +++ i386/i386.md (working copy) @@ -59,6 +59,7 @@ ;; Y -- print condition for XOP pcom* instruction. ;; + -- print a branch hint as 'cs' or 'ds' prefix ;; ; -- print a semicolon (after prefixes due to bug in older gas). +;; @ -- print a segment register of thread base pointer load ;; UNSPEC usage: @@ -821,6 +822,12 @@ ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) +;; Pointer size prefix for integer modes (Intel asm dialect) +(define_mode_attr iptrsize [(QI "BYTE") + (HI "WORD") + (SI "DWORD") + (DI "QWORD")]) + ;; Register class for integer modes. (define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")]) @@ -12042,50 +12049,28 @@ (clobber (reg:CC FLAGS_REG))])] "") -;; Load and add the thread base pointer from %gs:0. +;; Segment register for the thread base ptr load +(define_mode_attr tp_seg [(SI "gs") (DI "fs")]) -(define_insn "*load_tp_si" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(const_int 0)] UNSPEC_TP))] - "!TARGET_64BIT" - "mov{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}" - [(set_attr "type" "imov") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) - -(define_insn "*add_tp_si" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) - (match_operand:SI 1 "register_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" - "add{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}" - [(set_attr "type" "alu") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) - -(define_insn "*load_tp_di" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(const_int 0)] UNSPEC_TP))] - "TARGET_64BIT" - "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}" +;; Load and add the thread base pointer from %gs:0. +(define_insn "*load_tp_" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P [(const_int 0)] UNSPEC_TP))] + "" + "mov{}\t{%%:0, %0|%0, PTR :0}" [(set_attr "type" "imov") (set_attr "modrm" "0") (set_attr "length" "7") (set_attr "memory" "load") (set_attr "imm_disp" "false")]) -(define_insn "*add_tp_di" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP) - (match_operand:DI 1 "register_operand" "0"))) +(define_insn "*add_tp_" + [(set (match_operand:P 0 "register_operand" "=r") + (plus:P (unspec:P [(const_int 0)] UNSPEC_TP) + (match_operand:P 1 "register_operand" "0"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "add{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}" + "" + "add{}\t{%%:0, %0|%0, PTR :0}" [(set_attr "type" "alu") (set_attr "modrm" "0") (set_attr "length" "7") @@ -12219,8 +12204,6 @@ operands[4] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0]; emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1])); }) - -;; ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -17344,66 +17327,40 @@ (match_operand 1 "memory_operand" "")] "" { + rtx (*insn)(rtx, rtx); + #ifdef TARGET_THREAD_SSP_OFFSET - if (TARGET_64BIT) - emit_insn (gen_stack_tls_protect_set_di (operands[0], - GEN_INT (TARGET_THREAD_SSP_OFFSET))); - else - emit_insn (gen_stack_tls_protect_set_si (operands[0], - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); + insn = (TARGET_64BIT + ? gen_stack_tls_protect_set_di + : gen_stack_tls_protect_set_si); #else - if (TARGET_64BIT) - emit_insn (gen_stack_protect_set_di (operands[0], operands[1])); - else - emit_insn (gen_stack_protect_set_si (operands[0], operands[1])); + insn = (TARGET_64BIT + ? gen_stack_protect_set_di + : gen_stack_protect_set_si); #endif + + emit_insn (insn (operands[0], operands[1])); DONE; }) -(define_insn "stack_protect_set_si" - [(set (match_operand:SI 0 "memory_operand" "=m") - (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) - (set (match_scratch:SI 2 "=&r") (const_int 0)) +(define_insn "stack_protect_set_" + [(set (match_operand:P 0 "memory_operand" "=m") + (unspec:P [(match_operand:P 1 "memory_operand" "m")] UNSPEC_SP_SET)) + (set (match_scratch:P 2 "=&r") (const_int 0)) (clobber (reg:CC FLAGS_REG))] "" - "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2" - [(set_attr "type" "multi")]) - -(define_insn "stack_protect_set_di" - [(set (match_operand:DI 0 "memory_operand" "=m") - (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) - (set (match_scratch:DI 2 "=&r") (const_int 0)) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" + "mov{}\t{%1, %2|%2, %1}\;mov{}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_set_si" - [(set (match_operand:SI 0 "memory_operand" "=m") - (unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] - UNSPEC_SP_TLS_SET)) - (set (match_scratch:SI 2 "=&r") (const_int 0)) +(define_insn "stack_tls_protect_set_" + [(set (match_operand:P 0 "memory_operand" "=m") + (unspec:P [(match_operand:P 1 "const_int_operand" "i")] + UNSPEC_SP_TLS_SET)) + (set (match_scratch:P 2 "=&r") (const_int 0)) (clobber (reg:CC FLAGS_REG))] "" - "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2" - [(set_attr "type" "multi")]) - -(define_insn "stack_tls_protect_set_di" - [(set (match_operand:DI 0 "memory_operand" "=m") - (unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] - UNSPEC_SP_TLS_SET)) - (set (match_scratch:DI 2 "=&r") (const_int 0)) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - { - /* The kernel uses a different segment register for performance reasons; a - system call would not have to trash the userspace segment register, - which would be expensive */ - if (ix86_cmodel != CM_KERNEL) - return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; - else - return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; - } + "mov{}\t{%@:%P1, %2|%2, PTR %@:%P1}\;mov{}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" [(set_attr "type" "multi")]) (define_expand "stack_protect_test" @@ -17414,71 +17371,44 @@ { rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); + rtx (*insn)(rtx, rtx, rtx); + #ifdef TARGET_THREAD_SSP_OFFSET - if (TARGET_64BIT) - emit_insn (gen_stack_tls_protect_test_di (flags, operands[0], - GEN_INT (TARGET_THREAD_SSP_OFFSET))); - else - emit_insn (gen_stack_tls_protect_test_si (flags, operands[0], - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); + insn = (TARGET_64BIT + ? gen_stack_tls_protect_test_di + : gen_stack_tls_protect_test_si); #else - if (TARGET_64BIT) - emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1])); - else - emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); + insn = (TARGET_64BIT + ? gen_stack_protect_test_di + : gen_stack_protect_test_si); #endif + emit_insn (insn (flags, operands[0], operands[1])); + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), flags, const0_rtx, operands[2])); DONE; }) -(define_insn "stack_protect_test_si" +(define_insn "stack_protect_test_" [(set (match_operand:CCZ 0 "flags_reg_operand" "") - (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m") - (match_operand:SI 2 "memory_operand" "m")] + (unspec:CCZ [(match_operand:P 1 "memory_operand" "m") + (match_operand:P 2 "memory_operand" "m")] UNSPEC_SP_TEST)) - (clobber (match_scratch:SI 3 "=&r"))] + (clobber (match_scratch:P 3 "=&r"))] "" - "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}" - [(set_attr "type" "multi")]) - -(define_insn "stack_protect_test_di" - [(set (match_operand:CCZ 0 "flags_reg_operand" "") - (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m") - (match_operand:DI 2 "memory_operand" "m")] - UNSPEC_SP_TEST)) - (clobber (match_scratch:DI 3 "=&r"))] - "TARGET_64BIT" - "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}" + "mov{}\t{%1, %3|%3, %1}\;xor{}\t{%2, %3|%3, %2}" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_test_si" +(define_insn "stack_tls_protect_test_" [(set (match_operand:CCZ 0 "flags_reg_operand" "") - (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m") - (match_operand:SI 2 "const_int_operand" "i")] + (unspec:CCZ [(match_operand:P 1 "memory_operand" "m") + (match_operand:P 2 "const_int_operand" "i")] UNSPEC_SP_TLS_TEST)) - (clobber (match_scratch:SI 3 "=r"))] + (clobber (match_scratch:P 3 "=r"))] "" - "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR gs:%P2}" - [(set_attr "type" "multi")]) - -(define_insn "stack_tls_protect_test_di" - [(set (match_operand:CCZ 0 "flags_reg_operand" "") - (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m") - (match_operand:DI 2 "const_int_operand" "i")] - UNSPEC_SP_TLS_TEST)) - (clobber (match_scratch:DI 3 "=r"))] - "TARGET_64BIT" - { - /* The kernel uses a different segment register for performance reasons; a - system call would not have to trash the userspace segment register, - which would be expensive */ - if (ix86_cmodel != CM_KERNEL) - return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR fs:%P2}"; - else - return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR gs:%P2}"; - } + "mov{}\t{%1, %3|%3, %1}\;xor{}\t{%@:%P2, %3|%3, PTR %@:%P2}" [(set_attr "type" "multi")]) (define_insn "sse4_2_crc32" Index: i386/i386.c =================================================================== --- i386/i386.c (revision 163879) +++ i386/i386.c (working copy) @@ -12404,6 +12404,7 @@ get_some_local_dynamic_name (void) Y -- print condition for XOP pcom* instruction. + -- print a branch hint as 'cs' or 'ds' prefix ; -- print a semicolon (after prefixes due to bug in older gas). + @ -- print a segment register of thread base pointer load */ void @@ -12882,6 +12883,19 @@ ix86_print_operand (FILE *file, rtx x, i #endif return; + case '@': + if (ASSEMBLER_DIALECT == ASM_ATT) + putc ('%', file); + + /* The kernel uses a different segment register for performance + reasons; a system call would not have to trash the userspace + segment register, which would be expensive. */ + if (TARGET_64BIT && ix86_cmodel != CM_KERNEL) + fputs ("fs", file); + else + fputs ("gs", file); + return; + default: output_operand_lossage ("invalid operand code '%c'", code); } @@ -13012,7 +13026,8 @@ ix86_print_operand (FILE *file, rtx x, i static bool ix86_print_operand_punct_valid_p (unsigned char code) { - return (code == '*' || code == '+' || code == '&' || code == ';'); + return (code == '@' || code == '*' || code == '+' + || code == '&' || code == ';'); } /* Print a memory operand whose address is ADDR. */