diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2024-09-25 16:39:04 +0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2024-09-26 02:10:52 +0800 |
commit | c79cc30862d7255ca15884aa956d1ccfa279d86a (patch) | |
tree | 2c1f10426f43594c1215a20028ad5620c67c290b /gcc | |
parent | ed6dccd00d8eedc8f671133f90e6a0cd12f1f05d (diff) | |
download | gcc-c79cc30862d7255ca15884aa956d1ccfa279d86a.zip gcc-c79cc30862d7255ca15884aa956d1ccfa279d86a.tar.gz gcc-c79cc30862d7255ca15884aa956d1ccfa279d86a.tar.bz2 |
x86: Don't use address override with segment regsiter
Address override only applies to the (reg32) part in the thread address
fs:(reg32). Don't rewrite thread address like
(set (reg:CCZ 17 flags)
(compare:CCZ (reg:SI 98 [ __gmpfr_emax.0_1 ])
(mem/c:SI (plus:SI (plus:SI (unspec:SI [
(const_int 0 [0])
] UNSPEC_TP)
(reg:SI 107))
(const:SI (unspec:SI [
(symbol_ref:SI ("previous_emax") [flags 0x1a] <var_decl 0x7fffe9a11cf0 previous_emax>)
] UNSPEC_DTPOFF))) [1 previous_emax+0 S4 A32])))
if address override is used to avoid the invalid memory operand like
cmpl %fs:previous_emax@dtpoff(%eax), %r12d
gcc/
PR target/116839
* config/i386/i386.cc (ix86_rewrite_tls_address_1): Make it
static. Return if TLS address is thread register plus an integer
register.
gcc/testsuite/
PR target/116839
* gcc.target/i386/pr116839.c: New file.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.cc | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr116839.c | 48 |
2 files changed, 56 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 2f736a3..cfa84ed 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -12469,7 +12469,7 @@ ix86_tls_address_pattern_p (rtx op) } /* Rewrite *LOC so that it refers to a default TLS address space. */ -void +static void ix86_rewrite_tls_address_1 (rtx *loc) { subrtx_ptr_iterator::array_type array; @@ -12491,6 +12491,13 @@ ix86_rewrite_tls_address_1 (rtx *loc) if (GET_CODE (u) == UNSPEC && XINT (u, 1) == UNSPEC_TP) { + /* NB: Since address override only applies to the + (reg32) part in fs:(reg32), return if address + override is used. */ + if (Pmode != word_mode + && REG_P (XEXP (*x, 1 - i))) + return; + addr_space_t as = DEFAULT_TLS_SEG_REG; *x = XEXP (*x, 1 - i); diff --git a/gcc/testsuite/gcc.target/i386/pr116839.c b/gcc/testsuite/gcc.target/i386/pr116839.c new file mode 100644 index 0000000..e5df825 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr116839.c @@ -0,0 +1,48 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-mx32 -O2 -fPIC -mtls-dialect=gnu2" } */ +/* { dg-final { scan-assembler-not "cmpl\[ \t\]+%fs:previous_emax@dtpoff\\(%eax\\)" } } */ + +typedef long mpfr_prec_t; +typedef long mpfr_exp_t; +typedef struct { + mpfr_prec_t _mpfr_prec; +} __mpfr_struct; +typedef __mpfr_struct mpfr_t[1]; +extern _Thread_local mpfr_exp_t __gmpfr_emax; +static _Thread_local mpfr_exp_t previous_emax; +static _Thread_local mpfr_t bound_emax; +extern const mpfr_t __gmpfr_const_log2_RNDD; +extern const mpfr_t __gmpfr_const_log2_RNDU; + +typedef enum { + MPFR_RNDN=0, + MPFR_RNDZ, + MPFR_RNDU, + MPFR_RNDD, + MPFR_RNDA, + MPFR_RNDF, + MPFR_RNDNA=-1 +} mpfr_rnd_t; +typedef __mpfr_struct *mpfr_ptr; +typedef const __mpfr_struct *mpfr_srcptr; +void mpfr_mul (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t); + +void +foo (void) +{ + mpfr_exp_t saved_emax; + + if (__gmpfr_emax != previous_emax) + { + saved_emax = __gmpfr_emax; + + bound_emax->_mpfr_prec = 32; + + mpfr_mul (bound_emax, saved_emax < 0 ? + __gmpfr_const_log2_RNDD : __gmpfr_const_log2_RNDU, + MPFR_RNDU); + previous_emax = saved_emax; + __gmpfr_emax = saved_emax; + } +} |