summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-09-03 11:33:31 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-09-27 08:31:53 -0700
commitfb814f725b2bad36bfddde324754114ab91b5a45 (patch)
tree150b5770a8d396707fe5583fdbd04b6c9df8e1ec
parentfd31e41d19a76b19a8763cf03b68c29ec1279be4 (diff)
downloadgcc-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.md2
-rw-r--r--gcc/config/i386/predicates.md38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-7.c14
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 } } } } */