diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-09-03 11:33:31 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-09-27 08:31:53 -0700 |
commit | fb814f725b2bad36bfddde324754114ab91b5a45 (patch) | |
tree | 150b5770a8d396707fe5583fdbd04b6c9df8e1ec | |
parent | fd31e41d19a76b19a8763cf03b68c29ec1279be4 (diff) | |
download | gcc-hjl/got/gcc-5-branch.tar.gz |
Load address of external function from its GOT slothjl/got/gcc-5-branch
Load address of external function from its GOT slot for -fno-plt -fno-pic
if assembler and linker support R_386_GOT32X and R_X86_64_GOTPCRELX to
avoid the PLT slot. R_386_GOT32X and R_X86_64_GOTPCRELX instruct linker
to re-encode the instruction to convert loading function address from its
GOT slot to immediate if the function is defined locally.
gcc/
PR target/67400
* config/i386/i386.md (*cmp<mode>_1): Replace
nonimmediate_operand with ix86_cmp_destination_operand.
* config/i386/predicates.md (got_slot_operand): New.
(ix86_cmp_destination_operand): Likewise.
(x86_64_immediate_operand): Return false if got_slot_operand
returns true.
(x86_64_general_operand): Likewise.
gcc/testsuite/
PR target/67400
* gcc.target/i386/pr67400-7.c: New test.
-rw-r--r-- | gcc/config/i386/i386.md | 2 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 38 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr67400-7.c | 14 |
3 files changed, 52 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 3eb6cf6afd4..e9556ee03c4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1228,7 +1228,7 @@ (define_insn "*cmp<mode>_1" [(set (reg FLAGS_REG) - (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") + (compare (match_operand:SWI 0 "ix86_cmp_destination_operand" "<r>m,<r>") (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")))] "ix86_match_ccmode (insn, CCmode)" "cmp{<imodesuffix>}\t{%1, %0|%0, %1}" diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 4c9a7568c08..2d07ec3dd50 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -37,6 +37,38 @@ (and (match_code "reg") (match_test "GENERAL_REG_P (op)"))) +;; Return true if OP should be accessed by its GOT slot. +(define_predicate "got_slot_operand" + (match_code "symbol_ref") +{ + /* Load address of external function from its GOT slot for -fno-plt + -fno-pic if preferred. */ + if (!flag_pic && ix86_noplt_operand (op)) + { + if (TARGET_64BIT) + return ix86_cmodel == CM_SMALL && HAVE_LD_R_X86_64_GOTPCRELX; + else + return HAVE_LD_R_386_GOT32X; + } + return false; +}) + +;; Return true if OP is destination operand suitable for cmp +;; instruction. +(define_predicate "ix86_cmp_destination_operand" + (match_operand 0 "nonimmediate_operand") +{ + if (GET_CODE (op) == MEM) + { + op = ix86_noplt_addr_symbol_rtx (XEXP (op, 0)); + if (op) + /* Don't put the GOT slot on destination since linker + can't re-encode it as immediate operand. */ + return !got_slot_operand (op, GET_MODE (op)); + } + return true; +}) + ;; True if the operand is a nonimmediate operand with GENERAL class register. (define_predicate "nonimmediate_gr_operand" (if_then_else (match_code "reg") @@ -143,6 +175,9 @@ (define_predicate "x86_64_immediate_operand" (match_code "const_int,symbol_ref,label_ref,const") { + if (got_slot_operand (op, mode)) + return false; + if (!TARGET_64BIT) return immediate_operand (op, mode); @@ -364,7 +399,8 @@ (if_then_else (match_test "TARGET_64BIT") (ior (match_operand 0 "nonimmediate_operand") (match_operand 0 "x86_64_immediate_operand")) - (match_operand 0 "general_operand"))) + (and (not (match_operand 0 "got_slot_operand")) + (match_operand 0 "general_operand")))) ;; Return true if OP is non-VOIDmode general operand representable ;; on x86_64. This predicate is used in sign-extending conversion diff --git a/gcc/testsuite/gcc.target/i386/pr67400-7.c b/gcc/testsuite/gcc.target/i386/pr67400-7.c new file mode 100644 index 00000000000..58df4512d0f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67400-7.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-plt" } */ + +extern void bar (void); + +int +__attribute__((regparm(1))) +foo (void *p) +{ + return p == &bar; +} + +/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*bar@GOTPCREL" { target { { ! ia32 } && r_x86_64_gotpcrelx } } } } */ +/* { dg-final { scan-assembler "cmpl\[ \t\]*bar@GOT," { target { ia32 && r_386_got32x } } } } */ |