ix86: Don't match the 'm' constraint on x86_64_general_operand

Message ID 20211219200630.2325031-1-hjl.tools@gmail.com
State New
Headers
Series ix86: Don't match the 'm' constraint on x86_64_general_operand |

Commit Message

H.J. Lu Dec. 19, 2021, 8:06 p.m. UTC
  x86_64_general_operand is different from general_operand for 64-bit
target.  To avoid LRA selecting a memory operand which doesn't satisfy
x86_64_general_operand for 64-bit target:

1. Add a 'BM' constraint which is similar to the 'm' constraint, but
checks x86_64_general_operand for integers > 16 bits.
2. Replace the 'm' constraint on x86_64_general_operand with the 'BM'
constraint.

gcc/

	PR target/103762
	* config/i386/constraints.md (BM): New constraint.
	* config/i386/i386.md: Replace the 'm' constraint on
	x86_64_general_operand with the 'BM' constraint.
	* config/i386/predicates.md (ix86_memory_operand): New predicate.

gcc/testsuite/

	* gcc.target/i386/pr103762-1a.c: New test.
	* gcc.target/i386/pr103762-1b.c: Likewise.
	* gcc.target/i386/pr103762-1c.c: Likewise.
---
 gcc/config/i386/constraints.md              |   5 +
 gcc/config/i386/i386.md                     |  64 +-
 gcc/config/i386/predicates.md               |   6 +
 gcc/testsuite/gcc.target/i386/pr103762-1a.c | 647 ++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr103762-1b.c |   7 +
 gcc/testsuite/gcc.target/i386/pr103762-1c.c |   7 +
 6 files changed, 704 insertions(+), 32 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1c.c
  

Comments

Uros Bizjak Dec. 20, 2021, 8:08 a.m. UTC | #1
On Sun, Dec 19, 2021 at 9:06 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> x86_64_general_operand is different from general_operand for 64-bit
> target.  To avoid LRA selecting a memory operand which doesn't satisfy
> x86_64_general_operand for 64-bit target:
>
> 1. Add a 'BM' constraint which is similar to the 'm' constraint, but
> checks x86_64_general_operand for integers > 16 bits.
> 2. Replace the 'm' constraint on x86_64_general_operand with the 'BM'
> constraint.
>
> gcc/
>
>         PR target/103762
>         * config/i386/constraints.md (BM): New constraint.
>         * config/i386/i386.md: Replace the 'm' constraint on
>         x86_64_general_operand with the 'BM' constraint.
>         * config/i386/predicates.md (ix86_memory_operand): New predicate.
>
> gcc/testsuite/
>
>         * gcc.target/i386/pr103762-1a.c: New test.
>         * gcc.target/i386/pr103762-1b.c: Likewise.
>         * gcc.target/i386/pr103762-1c.c: Likewise.
> ---
>  gcc/config/i386/constraints.md              |   5 +
>  gcc/config/i386/i386.md                     |  64 +-
>  gcc/config/i386/predicates.md               |   6 +
>  gcc/testsuite/gcc.target/i386/pr103762-1a.c | 647 ++++++++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr103762-1b.c |   7 +
>  gcc/testsuite/gcc.target/i386/pr103762-1c.c |   7 +
>  6 files changed, 704 insertions(+), 32 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1a.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1b.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr103762-1c.c
>
> diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> index 6b291a02d88..6677285e518 100644
> --- a/gcc/config/i386/constraints.md
> +++ b/gcc/config/i386/constraints.md
> @@ -168,6 +168,7 @@
>  ;;  z  Constant call address operand.
>  ;;  C  Integer SSE constant with all bits set operand.
>  ;;  F  Floating-point SSE constant with all bits set operand.
> +;;  M  ix86 memory operand.
>
>  (define_constraint "Bf"
>    "@internal Flags register operand."
> @@ -232,6 +233,10 @@
>    (and (match_test "TARGET_SSE")
>         (match_operand 0 "float_vector_all_ones_operand")))
>
> +(define_constraint "BM"
> +  "@internal ix86 memory operand."
> +  (match_operand 0 "ix86_memory_operand"))
> +
>  ;; Integer constant constraints.
>  (define_constraint "Wb"
>    "Integer constant in the range 0 @dots{} 7, for 8-bit shifts."
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index d25453fe574..4f30819a1d9 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -1385,7 +1385,7 @@
>  (define_insn "*cmp<mode>_1"
>    [(set (reg FLAGS_REG)
>         (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
> -                (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")))]
> +                (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>BM")))]
>    "ix86_match_ccmode (insn, CCmode)"
>    "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
>    [(set_attr "type" "icmp")
> @@ -1395,7 +1395,7 @@
>    [(set (reg FLAGS_REG)
>         (compare
>           (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
> -                    (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
> +                    (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>BM"))
>           (const_int 0)))]
>    "ix86_match_ccmode (insn, CCGOCmode)"
>    "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
> @@ -5653,7 +5653,7 @@
>    [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r")
>         (plus:SWI48
>           (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r")
> -         (match_operand:SWI48 2 "x86_64_general_operand" "re,m,0,le")))
> +         (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
>  {
> @@ -5709,7 +5709,7 @@
>    [(set (match_operand:DI 0 "register_operand" "=r,r,r")
>         (zero_extend:DI
>           (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r")
> -                  (match_operand:SI 2 "x86_64_general_operand" "rme,0,le"))))
> +                  (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
>  {
> @@ -5967,7 +5967,7 @@
>         (compare
>           (plus:SWI
>             (match_operand:SWI 1 "nonimmediate_operand" "%0,0,<r>")
> -           (match_operand:SWI 2 "<general_operand>" "<r><i>,m,0"))
> +           (match_operand:SWI 2 "<general_operand>" "<r><i>,BM,0"))
>           (const_int 0)))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,<r>")
>         (plus:SWI (match_dup 1) (match_dup 2)))]
> @@ -6012,7 +6012,7 @@
>    [(set (reg FLAGS_REG)
>         (compare
>           (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
> -                  (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
> +                  (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
>           (const_int 0)))
>     (set (match_operand:DI 0 "register_operand" "=r,r")
>         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
> @@ -6097,7 +6097,7 @@
>  (define_insn "*addsi_3_zext"
>    [(set (reg FLAGS_REG)
>         (compare
> -         (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
> +         (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
>           (match_operand:SI 1 "nonimmediate_operand" "%0,r")))
>     (set (match_operand:DI 0 "register_operand" "=r,r")
>         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
> @@ -6801,7 +6801,7 @@
>    [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (minus:SWI
>           (match_operand:SWI 1 "nonimmediate_operand" "0,0")
> -         (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
> +         (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
>    "sub{<imodesuffix>}\t{%2, %0|%0, %2}"
> @@ -6812,7 +6812,7 @@
>    [(set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI
>           (minus:SI (match_operand:SI 1 "register_operand" "0")
> -                   (match_operand:SI 2 "x86_64_general_operand" "rme"))))
> +                   (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
>    "sub{l}\t{%2, %k0|%k0, %2}"
> @@ -6844,7 +6844,7 @@
>         (compare
>           (minus:SWI
>             (match_operand:SWI 1 "nonimmediate_operand" "0,0")
> -           (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
> +           (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
>           (const_int 0)))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (minus:SWI (match_dup 1) (match_dup 2)))]
> @@ -6858,7 +6858,7 @@
>    [(set (reg FLAGS_REG)
>         (compare
>           (minus:SI (match_operand:SI 1 "register_operand" "0")
> -                   (match_operand:SI 2 "x86_64_general_operand" "rme"))
> +                   (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
>           (const_int 0)))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI
> @@ -7111,7 +7111,7 @@
>  (define_insn "*sub<mode>_3"
>    [(set (reg FLAGS_REG)
>         (compare (match_operand:SWI 1 "nonimmediate_operand" "0,0")
> -                (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
> +                (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (minus:SWI (match_dup 1) (match_dup 2)))]
>    "ix86_match_ccmode (insn, CCmode)
> @@ -7187,7 +7187,7 @@
>  (define_insn "*subsi_3_zext"
>    [(set (reg FLAGS_REG)
>         (compare (match_operand:SI 1 "register_operand" "0")
> -                (match_operand:SI 2 "x86_64_general_operand" "rme")))
> +                (match_operand:SI 2 "x86_64_general_operand" "rBMe")))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI
>           (minus:SI (match_dup 1)
> @@ -7207,7 +7207,7 @@
>             (match_operator:SWI 4 "ix86_carry_flag_operator"
>              [(match_operand 3 "flags_reg_operand") (const_int 0)])
>             (match_operand:SWI 1 "nonimmediate_operand" "%0,0"))
> -         (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
> +         (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
>    "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
> @@ -7251,7 +7251,7 @@
>             (plus:SI (match_operator:SI 3 "ix86_carry_flag_operator"
>                       [(reg FLAGS_REG) (const_int 0)])
>                      (match_operand:SI 1 "register_operand" "%0"))
> -           (match_operand:SI 2 "x86_64_general_operand" "rme"))))
> +           (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
>    "adc{l}\t{%2, %k0|%k0, %2}"
> @@ -7377,7 +7377,7 @@
>             (match_operand:SWI 1 "nonimmediate_operand" "0,0")
>             (match_operator:SWI 4 "ix86_carry_flag_operator"
>              [(match_operand 3 "flags_reg_operand") (const_int 0)]))
> -         (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
> +         (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
>    "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
> @@ -7422,7 +7422,7 @@
>               (match_operand:SI 1 "register_operand" "0")
>               (match_operator:SI 3 "ix86_carry_flag_operator"
>                [(reg FLAGS_REG) (const_int 0)]))
> -           (match_operand:SI 2 "x86_64_general_operand" "rme"))))
> +           (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
>    "sbb{l}\t{%2, %k0|%k0, %2}"
> @@ -7498,7 +7498,7 @@
>  (define_insn "@sub<mode>3_carry_ccgz"
>    [(set (reg:CCGZ FLAGS_REG)
>         (unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
> -                     (match_operand:DWIH 2 "x86_64_general_operand" "rme")
> +                     (match_operand:DWIH 2 "x86_64_general_operand" "rBMe")
>                       (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
>                      UNSPEC_SBB))
>     (clobber (match_scratch:DWIH 0 "=r"))]
> @@ -7585,7 +7585,7 @@
>         (compare:CCC
>             (plus:SWI
>                 (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
> -               (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
> +               (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
>             (match_dup 1)))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (plus:SWI (match_dup 1) (match_dup 2)))]
> @@ -7616,7 +7616,7 @@
>         (compare:CCC
>           (plus:SI
>             (match_operand:SI 1 "nonimmediate_operand" "%0")
> -           (match_operand:SI 2 "x86_64_general_operand" "rme"))
> +           (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
>           (match_dup 1)))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
> @@ -7643,7 +7643,7 @@
>         (compare:CCC
>             (plus:SWI
>                 (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
> -               (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
> +               (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
>             (match_dup 2)))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (plus:SWI (match_dup 1) (match_dup 2)))]
> @@ -7657,7 +7657,7 @@
>         (compare:CCC
>           (plus:SI
>             (match_operand:SI 1 "nonimmediate_operand" "%0")
> -           (match_operand:SI 2 "x86_64_general_operand" "rme"))
> +           (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
>           (match_dup 2)))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
> @@ -8001,7 +8001,7 @@
>    [(set (match_operand:SWIM248 0 "register_operand" "=r,r,r")
>         (mult:SWIM248
>           (match_operand:SWIM248 1 "nonimmediate_operand" "%rm,rm,0")
> -         (match_operand:SWIM248 2 "<general_operand>" "K,<i>,mr")))
> +         (match_operand:SWIM248 2 "<general_operand>" "K,<i>,BMr")))
>     (clobber (reg:CC FLAGS_REG))]
>    "!(MEM_P (operands[1]) && MEM_P (operands[2]))"
>    "@
> @@ -8037,7 +8037,7 @@
>    [(set (match_operand:DI 0 "register_operand" "=r,r,r")
>         (zero_extend:DI
>           (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
> -                  (match_operand:SI 2 "x86_64_general_operand" "K,e,mr"))))
> +                  (match_operand:SI 2 "x86_64_general_operand" "K,e,BMr"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT
>     && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
> @@ -9711,7 +9711,7 @@
>    [(set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI
>           (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
> -                 (match_operand:SI 2 "x86_64_general_operand" "rme"))))
> +                 (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
>    "and{l}\t{%2, %k0|%k0, %2}"
> @@ -9721,7 +9721,7 @@
>  (define_insn "*and<mode>_1"
>    [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,Ya,?k")
>         (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,qm,k")
> -                  (match_operand:SWI24 2 "<general_operand>" "r<i>,m,L,k")))
> +                  (match_operand:SWI24 2 "<general_operand>" "r<i>,BM,L,k")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (AND, <MODE>mode, operands)"
>    "@
> @@ -9903,7 +9903,7 @@
>    [(set (reg FLAGS_REG)
>         (compare (and:SI
>                   (match_operand:SI 1 "nonimmediate_operand" "%0")
> -                 (match_operand:SI 2 "x86_64_general_operand" "rme"))
> +                 (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
>                  (const_int 0)))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
> @@ -9946,7 +9946,7 @@
>    [(set (reg FLAGS_REG)
>         (compare (and:SWI124
>                   (match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
> -                 (match_operand:SWI124 2 "<general_operand>" "<r><i>,m"))
> +                 (match_operand:SWI124 2 "<general_operand>" "<r><i>,BM"))
>                  (const_int 0)))
>     (set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>m,<r>")
>         (and:SWI124 (match_dup 1) (match_dup 2)))]
> @@ -10260,7 +10260,7 @@
>    [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,?k")
>         (any_or:SWI248
>          (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,k")
> -        (match_operand:SWI248 2 "<general_operand>" "r<i>,m,k")))
> +        (match_operand:SWI248 2 "<general_operand>" "r<i>,BM,k")))
>     (clobber (reg:CC FLAGS_REG))]
>    "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
>    "@
> @@ -10328,7 +10328,7 @@
>    [(set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI
>          (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
> -                   (match_operand:SI 2 "x86_64_general_operand" "rme"))))
> +                   (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
>     (clobber (reg:CC FLAGS_REG))]
>    "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
>    "<logic>{l}\t{%2, %k0|%k0, %2}"
> @@ -10431,7 +10431,7 @@
>    [(set (reg FLAGS_REG)
>         (compare (any_or:SWI
>                   (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
> -                 (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
> +                 (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
>                  (const_int 0)))
>     (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
>         (any_or:SWI (match_dup 1) (match_dup 2)))]
> @@ -10446,7 +10446,7 @@
>  (define_insn "*<code>si_2_zext"
>    [(set (reg FLAGS_REG)
>         (compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
> -                           (match_operand:SI 2 "x86_64_general_operand" "rme"))
> +                           (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
>                  (const_int 0)))
>     (set (match_operand:DI 0 "register_operand" "=r")
>         (zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))]
> diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
> index 770e2f0c0dd..cfc0a50e239 100644
> --- a/gcc/config/i386/predicates.md
> +++ b/gcc/config/i386/predicates.md
> @@ -1199,6 +1199,12 @@
>    (and (match_operand 0 "memory_operand")
>         (not (match_test "x86_extended_reg_mentioned_p (op)"))))
>
> +;; Return true if OP is a memory operand representable on ix86.
> +(define_predicate "ix86_memory_operand"
> +  (and (match_operand 0 "memory_operand")
> +       (ior (match_test "mode == QImode || mode == HImode")
> +           (match_operand 0 "x86_64_general_operand"))))

The "mode" variable represents the mode of the predicate, not the operand.

Please introduce another mode attribute (perhaps "m") and define it like this:

(define_mode_attr m [(QI "m") (HI "m") (SI "BM") (DI "BM")])

Then you can define the "BM" constraint directly to x86_64_general_operand.

Uros.

> +
>  ;; Return true for RTX codes that force SImode address.
>  (define_predicate "SImode_address_operand"
>    (match_code "subreg,zero_extend,and"))
> diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1a.c b/gcc/testsuite/gcc.target/i386/pr103762-1a.c
> new file mode 100644
> index 00000000000..c9e75bc12d8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr103762-1a.c
> @@ -0,0 +1,647 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -std=gnu11 -fgnu89-inline" } */
> +/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
> +/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
> +
> +typedef unsigned long int size_t;
> +typedef long long int intmax_t;
> +typedef unsigned long long int uintmax_t;
> +typedef unsigned long long int uint64_t;
> +typedef intmax_t tunable_num_t;
> +typedef union
> +{
> +  tunable_num_t numval;
> +  const char *strval;
> +} tunable_val_t;
> +enum
> +{
> +  HWCAP_X86_SSE2 = 1 << 0,
> +  HWCAP_X86_64 = 1 << 1,
> +  HWCAP_X86_AVX512_1 = 1 << 2
> +};
> +typedef void (*tunable_callback_t) (tunable_val_t *);
> +extern void *__minimal_malloc (size_t n)
> +    __attribute__ ((visibility ("hidden")));
> +extern int __libc_enable_secure __attribute__ ((section (".data.rel.ro")));
> +extern uint64_t _dl_strtoul (const char *, char **)
> +    __attribute__ ((visibility ("hidden")));
> +extern void _dl_fatal_printf (const char *fmt, ...)
> +    __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__));
> +typedef enum
> +{
> +  glibc_rtld_nns,
> +  glibc_elision_skip_lock_after_retries,
> +  glibc_malloc_trim_threshold,
> +  glibc_malloc_perturb,
> +  glibc_cpu_x86_shared_cache_size,
> +  glibc_pthread_rseq,
> +  glibc_mem_tagging,
> +  glibc_elision_tries,
> +  glibc_elision_enable,
> +  glibc_malloc_hugetlb,
> +  glibc_cpu_x86_rep_movsb_threshold,
> +  glibc_malloc_mxfast,
> +  glibc_rtld_dynamic_sort,
> +  glibc_elision_skip_lock_busy,
> +  glibc_malloc_top_pad,
> +  glibc_cpu_x86_rep_stosb_threshold,
> +  glibc_cpu_x86_non_temporal_threshold,
> +  glibc_cpu_x86_shstk,
> +  glibc_pthread_stack_cache_size,
> +  glibc_cpu_hwcap_mask,
> +  glibc_malloc_mmap_max,
> +  glibc_elision_skip_trylock_internal_abort,
> +  glibc_malloc_tcache_unsorted_limit,
> +  glibc_cpu_x86_ibt,
> +  glibc_cpu_hwcaps,
> +  glibc_elision_skip_lock_internal_abort,
> +  glibc_malloc_arena_max,
> +  glibc_malloc_mmap_threshold,
> +  glibc_cpu_x86_data_cache_size,
> +  glibc_malloc_tcache_count,
> +  glibc_malloc_arena_test,
> +  glibc_pthread_mutex_spin_count,
> +  glibc_rtld_optional_static_tls,
> +  glibc_malloc_tcache_max,
> +  glibc_malloc_check,
> +} tunable_id_t;
> +typedef enum
> +{
> +  TUNABLE_TYPE_INT_32,
> +  TUNABLE_TYPE_UINT_64,
> +  TUNABLE_TYPE_SIZE_T,
> +  TUNABLE_TYPE_STRING
> +} tunable_type_code_t;
> +typedef struct
> +{
> +  tunable_type_code_t type_code;
> +  tunable_num_t min;
> +  tunable_num_t max;
> +} tunable_type_t;
> +typedef enum
> +{
> +  TUNABLE_SECLEVEL_SXID_ERASE = 0,
> +  TUNABLE_SECLEVEL_SXID_IGNORE = 1,
> +  TUNABLE_SECLEVEL_NONE = 2,
> +} tunable_seclevel_t;
> +struct _tunable
> +{
> +  const char name[42];
> +  tunable_type_t type;
> +  tunable_val_t val;
> +  _Bool initialized;
> +  tunable_seclevel_t security_level;
> +  const char env_alias[23];
> +};
> +typedef struct _tunable tunable_t;
> +extern _Bool unsigned_tunable_type (tunable_type_code_t t);
> +
> +static tunable_t tunable_list[] __attribute__ ((section (".data.rel.ro"))) = {
> +  { "glibc"
> +    "."
> +    "rtld"
> +    "."
> +    "nns",
> +    { TUNABLE_TYPE_SIZE_T, 1, 16 },
> +    { .numval = 4 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "skip_lock_after_retries",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    { .numval = 3 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "trim_threshold",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_TRIM_THRESHOLD_" },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "perturb",
> +    { TUNABLE_TYPE_INT_32, 0, 0xff },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_PERTURB_" },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_shared_cache_size",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "pthread"
> +    "."
> +    "rseq",
> +    { TUNABLE_TYPE_INT_32, 0, 1 },
> +    { .numval = 1 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "mem"
> +    "."
> +    "tagging",
> +    { TUNABLE_TYPE_INT_32, 0, 255 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "tries",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    { .numval = 3 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "enable",
> +    { TUNABLE_TYPE_INT_32, 0, 1 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "hugetlb",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_rep_movsb_threshold",
> +    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "mxfast",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "rtld"
> +    "."
> +    "dynamic_sort",
> +    { TUNABLE_TYPE_INT_32, 1, 2 },
> +    { .numval = 2 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "skip_lock_busy",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    { .numval = 3 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "top_pad",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_TOP_PAD_" },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_rep_stosb_threshold",
> +    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
> +    { .numval = 2048 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_non_temporal_threshold",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_shstk",
> +    { TUNABLE_TYPE_STRING, 0, 0 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "pthread"
> +    "."
> +    "stack_cache_size",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    { .numval = 41943040 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "hwcap_mask",
> +    { TUNABLE_TYPE_UINT_64, 0, (18446744073709551615UL) },
> +    { .numval = (HWCAP_X86_64 | HWCAP_X86_AVX512_1) },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    "LD_HWCAP_MASK" },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "mmap_max",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_MMAP_MAX_" },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "skip_trylock_internal_abort",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    { .numval = 3 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "tcache_unsorted_limit",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_ibt",
> +    { TUNABLE_TYPE_STRING, 0, 0 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "hwcaps",
> +    { TUNABLE_TYPE_STRING, 0, 0 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "elision"
> +    "."
> +    "skip_lock_internal_abort",
> +    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
> +    { .numval = 3 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "arena_max",
> +    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_ARENA_MAX" },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "mmap_threshold",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_MMAP_THRESHOLD_" },
> +  { "glibc"
> +    "."
> +    "cpu"
> +    "."
> +    "x86_data_cache_size",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "tcache_count",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "arena_test",
> +    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_IGNORE,
> +    "MALLOC_ARENA_TEST" },
> +  { "glibc"
> +    "."
> +    "pthread"
> +    "."
> +    "mutex_spin_count",
> +    { TUNABLE_TYPE_INT_32, 0, 32767 },
> +    { .numval = 100 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "rtld"
> +    "."
> +    "optional_static_tls",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    { .numval = 512 },
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "tcache_max",
> +    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    { 0 } },
> +  { "glibc"
> +    "."
> +    "malloc"
> +    "."
> +    "check",
> +    { TUNABLE_TYPE_INT_32, 0, 3 },
> +    {},
> +    ((void *)0),
> +    TUNABLE_SECLEVEL_SXID_ERASE,
> +    "MALLOC_CHECK_" },
> +};
> +extern void __tunables_init (char **);
> +extern void __tunables_print (void);
> +extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
> +extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
> +                               tunable_num_t *);
> +static __inline __attribute__ ((__always_inline__)) _Bool
> +tunable_val_lt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
> +{
> +  if (unsigned_cmp)
> +    return (uintmax_t)lhs < (uintmax_t)rhs;
> +  else
> +    return lhs < rhs;
> +}
> +static __inline __attribute__ ((__always_inline__)) _Bool
> +tunable_val_gt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
> +{
> +  if (unsigned_cmp)
> +    return (uintmax_t)lhs > (uintmax_t)rhs;
> +  else
> +    return lhs > rhs;
> +}
> +static __inline __attribute__ ((__always_inline__)) _Bool
> +tunable_is_name (const char *orig, const char *envname)
> +{
> +  for (; *orig != '\0' && *envname != '\0'; envname++, orig++)
> +    if (*orig != *envname)
> +      break;
> +  if (*orig == '\0' && *envname == '=')
> +    return 1;
> +  else
> +    return 0;
> +}
> +static char *
> +tunables_strdup (const char *in)
> +{
> +  size_t i = 0;
> +  while (in[i++] != '\0')
> +    ;
> +  char *out = __minimal_malloc (i + 1);
> +  if (out == ((void *)0))
> +    _dl_fatal_printf ("failed to allocate memory to process tunables\n");
> +  while (i-- > 0)
> +    out[i] = in[i];
> +  return out;
> +}
> +static char **
> +get_next_env (char **envp, char **name, size_t *namelen, char **val,
> +              char ***prev_envp)
> +{
> +  while (envp != ((void *)0) && *envp != ((void *)0))
> +    {
> +      char **prev = envp;
> +      char *envline = *envp++;
> +      int len = 0;
> +      while (envline[len] != '\0' && envline[len] != '=')
> +        len++;
> +      if (envline[len] == '\0')
> +        continue;
> +      *name = envline;
> +      *namelen = len;
> +      *val = &envline[len + 1];
> +      *prev_envp = prev;
> +      return envp;
> +    }
> +  return ((void *)0);
> +}
> +static void
> +do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
> +                       const tunable_num_t *minp, const tunable_num_t *maxp)
> +{
> +  tunable_num_t val, min, max;
> +  if (cur->type.type_code == TUNABLE_TYPE_STRING)
> +    {
> +      cur->val.strval = valp->strval;
> +      cur->initialized = 1;
> +      return;
> +    }
> +  _Bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
> +  val = valp->numval;
> +  min = minp != ((void *)0) ? *minp : cur->type.min;
> +  max = maxp != ((void *)0) ? *maxp : cur->type.max;
> +  if (tunable_val_lt (min, cur->type.min, unsigned_cmp))
> +    min = cur->type.min;
> +  if (tunable_val_gt (max, cur->type.max, unsigned_cmp))
> +    max = cur->type.max;
> +  if (tunable_val_gt (min, max, unsigned_cmp))
> +    {
> +      min = cur->type.min;
> +      max = cur->type.max;
> +    }
> +  if (tunable_val_lt (val, min, unsigned_cmp)
> +      || tunable_val_lt (max, val, unsigned_cmp))
> +    return;
> +  cur->val.numval = val;
> +  cur->type.min = min;
> +  cur->type.max = max;
> +  cur->initialized = 1;
> +}
> +static void
> +tunable_initialize (tunable_t *cur, const char *strval)
> +{
> +  tunable_val_t val;
> +  if (cur->type.type_code != TUNABLE_TYPE_STRING)
> +    val.numval = (tunable_num_t)_dl_strtoul (strval, ((void *)0));
> +  else
> +    val.strval = strval;
> +  do_tunable_update_val (cur, &val, ((void *)0), ((void *)0));
> +}
> +static void
> +parse_tunables (char *tunestr, char *valstring)
> +{
> +  if (tunestr == ((void *)0) || *tunestr == '\0')
> +    return;
> +  char *p = tunestr;
> +  size_t off = 0;
> +  while (1)
> +    {
> +      char *name = p;
> +      size_t len = 0;
> +      while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
> +        len++;
> +      if (p[len] == '\0')
> +        {
> +          if (__libc_enable_secure)
> +            tunestr[off] = '\0';
> +          return;
> +        }
> +      if (p[len] == ':')
> +        {
> +          p += len + 1;
> +          continue;
> +        }
> +      p += len + 1;
> +      char *value = &valstring[p - tunestr];
> +      len = 0;
> +      while (p[len] != ':' && p[len] != '\0')
> +        len++;
> +      for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
> +        {
> +          tunable_t *cur = &tunable_list[i];
> +          if (tunable_is_name (cur->name, name))
> +            {
> +              if (__libc_enable_secure)
> +                {
> +                  if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
> +                    {
> +                      if (off > 0)
> +                        tunestr[off++] = ':';
> +                      const char *n = cur->name;
> +                      while (*n != '\0')
> +                        tunestr[off++] = *n++;
> +                      tunestr[off++] = '=';
> +                      for (size_t j = 0; j < len; j++)
> +                        tunestr[off++] = value[j];
> +                    }
> +                  if (cur->security_level != TUNABLE_SECLEVEL_NONE)
> +                    break;
> +                }
> +              value[len] = '\0';
> +              tunable_initialize (cur, value);
> +              break;
> +            }
> +        }
> +      if (p[len] != '\0')
> +        p += len + 1;
> +    }
> +}
> +void
> +__tunables_init (char **envp)
> +{
> +  char *envname = ((void *)0);
> +  char *envval = ((void *)0);
> +  size_t len = 0;
> +  char **prev_envp = envp;
> +  while ((envp = get_next_env (envp, &envname, &len, &envval, &prev_envp))
> +         != ((void *)0))
> +    {
> +      if (tunable_is_name ("GLIBC_TUNABLES", envname))
> +        {
> +          char *new_env = tunables_strdup (envname);
> +          if (new_env != ((void *)0))
> +            parse_tunables (new_env + len + 1, envval);
> +          *prev_envp = new_env;
> +          continue;
> +        }
> +      for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
> +        {
> +          tunable_t *cur = &tunable_list[i];
> +          const char *name = cur->env_alias;
> +          if (tunable_is_name (name, envname))
> +            {
> +              tunable_initialize (cur, envval);
> +              break;
> +            }
> +        }
> +    }
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1b.c b/gcc/testsuite/gcc.target/i386/pr103762-1b.c
> new file mode 100644
> index 00000000000..391f51cf7f1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr103762-1b.c
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target pie } */
> +/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpie" } */
> +/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
> +/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
> +
> +#include "pr103762-1a.c"
> diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1c.c b/gcc/testsuite/gcc.target/i386/pr103762-1c.c
> new file mode 100644
> index 00000000000..4667b06c171
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr103762-1c.c
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target fpic } */
> +/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpic" } */
> +/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
> +/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
> +
> +#include "pr103762-1a.c"
> --
> 2.33.1
>
  
Jakub Jelinek Dec. 20, 2021, 2:53 p.m. UTC | #2
On Sun, Dec 19, 2021 at 12:06:30PM -0800, H.J. Lu via Gcc-patches wrote:
> --- a/gcc/config/i386/predicates.md
> +++ b/gcc/config/i386/predicates.md
> @@ -1199,6 +1199,12 @@
>    (and (match_operand 0 "memory_operand")
>         (not (match_test "x86_extended_reg_mentioned_p (op)"))))
>  
> +;; Return true if OP is a memory operand representable on ix86.
> +(define_predicate "ix86_memory_operand"
> +  (and (match_operand 0 "memory_operand")
> +       (ior (match_test "mode == QImode || mode == HImode")
> +	    (match_operand 0 "x86_64_general_operand"))))

I must be missing something, but how can this work?
x86_64_general_operand is:
(define_predicate "x86_64_general_operand"
  (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 so for non-immediates like MEMs it is just a normal memory_operand.

	Jakub
  
H.J. Lu Dec. 20, 2021, 7:44 p.m. UTC | #3
On Mon, Dec 20, 2021 at 6:53 AM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Sun, Dec 19, 2021 at 12:06:30PM -0800, H.J. Lu via Gcc-patches wrote:
> > --- a/gcc/config/i386/predicates.md
> > +++ b/gcc/config/i386/predicates.md
> > @@ -1199,6 +1199,12 @@
> >    (and (match_operand 0 "memory_operand")
> >         (not (match_test "x86_extended_reg_mentioned_p (op)"))))
> >
> > +;; Return true if OP is a memory operand representable on ix86.
> > +(define_predicate "ix86_memory_operand"
> > +  (and (match_operand 0 "memory_operand")
> > +       (ior (match_test "mode == QImode || mode == HImode")
> > +         (match_operand 0 "x86_64_general_operand"))))
>
> I must be missing something, but how can this work?
> x86_64_general_operand is:
> (define_predicate "x86_64_general_operand"
>   (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 so for non-immediates like MEMs it is just a normal memory_operand.
>
>         Jakub
>

The problem is in

(define_memory_constraint "TARGET_MEM_CONSTRAINT"
  "Matches any valid memory."
  (and (match_code "mem")
       (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
                                                 MEM_ADDR_SPACE (op))")))

define_register_constraint allows LRA to convert the operand to the form
'(mem (reg X))', where X is a base register.  I am testing the v2 patch with

;; NB: Similar to 'm', but don't use define_memory_constraint on x86-64
;; to prevent LRA from converting the operand to the form '(mem (reg X))'
;; where X is a base register.
(define_constraint "BM"
  "@internal x86-64 memory operand."
  (and (match_code "mem")
       (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
                                                 MEM_ADDR_SPACE (op))")))

;; Memory operand constraint for word modes.
(define_mode_attr m [(QI "m") (HI "m") (SI "BM") (DI "BM")])
  
Jakub Jelinek Dec. 20, 2021, 8:37 p.m. UTC | #4
On Mon, Dec 20, 2021 at 11:44:08AM -0800, H.J. Lu wrote:
> The problem is in
> 
> (define_memory_constraint "TARGET_MEM_CONSTRAINT"
>   "Matches any valid memory."
>   (and (match_code "mem")
>        (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
>                                                  MEM_ADDR_SPACE (op))")))
> 
> define_register_constraint allows LRA to convert the operand to the form
> '(mem (reg X))', where X is a base register.  I am testing the v2 patch with

If you mean replacing an immediate with a MEM containing that immediate,
isn't that often the right thing though?
I mean, if the register pressure is high and options are either spill some
register, set it to immediate, use it in one instruction and then fill the
spilled register (i.e. 2 memory loads), compared to a MEM use on the
arithmetic instruction one MEM seems cheaper to me.  With -fPIC and the
cst needing runtime relocation slightly less so of course.

The code due to ivopts is trying to have something like
  size_t a = (size_t) &tunable_list;
  size_t b = 0xffffffffffffffa8 - a;
  size_t c = x + b;
and for that cst - &symbol one needs actually 2 registers, one to hold the
constant and one to hold the (%rip) based address.
(insn 790 789 791 111 (set (reg:DI 292)
        (const_int -88 [0xffffffffffffffa8])) "dl-tunables.c":304:15 76 {*movdi_internal}
     (nil))
(insn 791 790 792 111 (set (reg:DI 293)
        (symbol_ref:DI ("tunable_list") [flags 0x2]  <var_decl 0x7f3460aa9cf0 tunable_list>)) "dl-tunables.c":304:15 76 {*movdi_internal}
     (nil))
(insn 792 791 793 111 (parallel [
            (set (reg:DI 291)
                (minus:DI (reg:DI 292)
                    (reg:DI 293)))
            (clobber (reg:CC 17 flags))
        ]) "dl-tunables.c":304:15 299 {*subdi_1}
     (nil))
(insn 793 792 794 111 (parallel [
            (set (reg:DI 294)
                (plus:DI (reg:DI 291)
                    (reg:DI 198 [ ivtmp.176 ])))
            (clobber (reg:CC 17 flags))
        ]) "dl-tunables.c":304:15 226 {*adddi_1}
     (nil))
It would be smarter to rewrite the above into a lea 88+tunable_list(%rip), %temp1
and use a subtraction instead of addition in the last insn above, or of
course in the particular case even consider the following 2 instructions
that do:
(insn 794 793 795 111 (set (reg:DI 296)
        (symbol_ref:DI ("tunable_list") [flags 0x2]  <var_decl 0x7f3460aa9cf0 tunable_list>)) "dl-tunables.c":304:15 76 {*movdi_internal}
     (nil))
(insn 795 794 796 111 (parallel [
            (set (reg:DI 295 [ cur ])
                (plus:DI (reg:DI 294)
                    (reg:DI 296)))
            (clobber (reg:CC 17 flags))
        ]) "dl-tunables.c":304:15 226 {*adddi_1}
     (nil))
and find out that &tuneble_list - &tuneble_list is 0 and we don't need it at
all.  Guess we don't figure that out due to the cast of one of those
addresses to size_t and the other one used in POINTER_PLUS_EXPR as normal
pointer.

	Jakub
  

Patch

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 6b291a02d88..6677285e518 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -168,6 +168,7 @@ 
 ;;  z  Constant call address operand.
 ;;  C  Integer SSE constant with all bits set operand.
 ;;  F  Floating-point SSE constant with all bits set operand.
+;;  M  ix86 memory operand.
 
 (define_constraint "Bf"
   "@internal Flags register operand."
@@ -232,6 +233,10 @@ 
   (and (match_test "TARGET_SSE")
        (match_operand 0 "float_vector_all_ones_operand")))
 
+(define_constraint "BM"
+  "@internal ix86 memory operand."
+  (match_operand 0 "ix86_memory_operand"))
+
 ;; Integer constant constraints.
 (define_constraint "Wb"
   "Integer constant in the range 0 @dots{} 7, for 8-bit shifts."
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d25453fe574..4f30819a1d9 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1385,7 +1385,7 @@ 
 (define_insn "*cmp<mode>_1"
   [(set (reg FLAGS_REG)
 	(compare (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
-		 (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")))]
+		 (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>BM")))]
   "ix86_match_ccmode (insn, CCmode)"
   "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
   [(set_attr "type" "icmp")
@@ -1395,7 +1395,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare
 	  (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
-		     (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
+		     (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>BM"))
 	  (const_int 0)))]
   "ix86_match_ccmode (insn, CCGOCmode)"
   "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
@@ -5653,7 +5653,7 @@ 
   [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r")
 	(plus:SWI48
 	  (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r")
-	  (match_operand:SWI48 2 "x86_64_general_operand" "re,m,0,le")))
+	  (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
 {
@@ -5709,7 +5709,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
 	(zero_extend:DI
 	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r")
-		   (match_operand:SI 2 "x86_64_general_operand" "rme,0,le"))))
+		   (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
 {
@@ -5967,7 +5967,7 @@ 
 	(compare
 	  (plus:SWI
 	    (match_operand:SWI 1 "nonimmediate_operand" "%0,0,<r>")
-	    (match_operand:SWI 2 "<general_operand>" "<r><i>,m,0"))
+	    (match_operand:SWI 2 "<general_operand>" "<r><i>,BM,0"))
 	  (const_int 0)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,<r>")
 	(plus:SWI (match_dup 1) (match_dup 2)))]
@@ -6012,7 +6012,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare
 	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
-		   (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
+		   (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
 	  (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r,r")
 	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -6097,7 +6097,7 @@ 
 (define_insn "*addsi_3_zext"
   [(set (reg FLAGS_REG)
 	(compare
-	  (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
+	  (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
 	  (match_operand:SI 1 "nonimmediate_operand" "%0,r")))
    (set (match_operand:DI 0 "register_operand" "=r,r")
 	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -6801,7 +6801,7 @@ 
   [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(minus:SWI
 	  (match_operand:SWI 1 "nonimmediate_operand" "0,0")
-	  (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+	  (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
   "sub{<imodesuffix>}\t{%2, %0|%0, %2}"
@@ -6812,7 +6812,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI
 	  (minus:SI (match_operand:SI 1 "register_operand" "0")
-		    (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+		    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sub{l}\t{%2, %k0|%k0, %2}"
@@ -6844,7 +6844,7 @@ 
 	(compare
 	  (minus:SWI
 	    (match_operand:SWI 1 "nonimmediate_operand" "0,0")
-	    (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+	    (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
 	  (const_int 0)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(minus:SWI (match_dup 1) (match_dup 2)))]
@@ -6858,7 +6858,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare
 	  (minus:SI (match_operand:SI 1 "register_operand" "0")
-		    (match_operand:SI 2 "x86_64_general_operand" "rme"))
+		    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
 	  (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI
@@ -7111,7 +7111,7 @@ 
 (define_insn "*sub<mode>_3"
   [(set (reg FLAGS_REG)
 	(compare (match_operand:SWI 1 "nonimmediate_operand" "0,0")
-		 (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+		 (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(minus:SWI (match_dup 1) (match_dup 2)))]
   "ix86_match_ccmode (insn, CCmode)
@@ -7187,7 +7187,7 @@ 
 (define_insn "*subsi_3_zext"
   [(set (reg FLAGS_REG)
 	(compare (match_operand:SI 1 "register_operand" "0")
-		 (match_operand:SI 2 "x86_64_general_operand" "rme")))
+		 (match_operand:SI 2 "x86_64_general_operand" "rBMe")))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI
 	  (minus:SI (match_dup 1)
@@ -7207,7 +7207,7 @@ 
 	    (match_operator:SWI 4 "ix86_carry_flag_operator"
 	     [(match_operand 3 "flags_reg_operand") (const_int 0)])
 	    (match_operand:SWI 1 "nonimmediate_operand" "%0,0"))
-	  (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+	  (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
   "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
@@ -7251,7 +7251,7 @@ 
 	    (plus:SI (match_operator:SI 3 "ix86_carry_flag_operator"
 		      [(reg FLAGS_REG) (const_int 0)])
 		     (match_operand:SI 1 "register_operand" "%0"))
-	    (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+	    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
   "adc{l}\t{%2, %k0|%k0, %2}"
@@ -7377,7 +7377,7 @@ 
 	    (match_operand:SWI 1 "nonimmediate_operand" "0,0")
 	    (match_operator:SWI 4 "ix86_carry_flag_operator"
 	     [(match_operand 3 "flags_reg_operand") (const_int 0)]))
-	  (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+	  (match_operand:SWI 2 "<general_operand>" "<r><i>,BM")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
   "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
@@ -7422,7 +7422,7 @@ 
 	      (match_operand:SI 1 "register_operand" "0")
 	      (match_operator:SI 3 "ix86_carry_flag_operator"
 	       [(reg FLAGS_REG) (const_int 0)]))
-	    (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+	    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sbb{l}\t{%2, %k0|%k0, %2}"
@@ -7498,7 +7498,7 @@ 
 (define_insn "@sub<mode>3_carry_ccgz"
   [(set (reg:CCGZ FLAGS_REG)
 	(unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
-		      (match_operand:DWIH 2 "x86_64_general_operand" "rme")
+		      (match_operand:DWIH 2 "x86_64_general_operand" "rBMe")
 		      (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
 		     UNSPEC_SBB))
    (clobber (match_scratch:DWIH 0 "=r"))]
@@ -7585,7 +7585,7 @@ 
 	(compare:CCC
 	    (plus:SWI
 		(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
-		(match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+		(match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
 	    (match_dup 1)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(plus:SWI (match_dup 1) (match_dup 2)))]
@@ -7616,7 +7616,7 @@ 
 	(compare:CCC
 	  (plus:SI
 	    (match_operand:SI 1 "nonimmediate_operand" "%0")
-	    (match_operand:SI 2 "x86_64_general_operand" "rme"))
+	    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
 	  (match_dup 1)))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -7643,7 +7643,7 @@ 
 	(compare:CCC
 	    (plus:SWI
 		(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
-		(match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+		(match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
 	    (match_dup 2)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(plus:SWI (match_dup 1) (match_dup 2)))]
@@ -7657,7 +7657,7 @@ 
 	(compare:CCC
 	  (plus:SI
 	    (match_operand:SI 1 "nonimmediate_operand" "%0")
-	    (match_operand:SI 2 "x86_64_general_operand" "rme"))
+	    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
 	  (match_dup 2)))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -8001,7 +8001,7 @@ 
   [(set (match_operand:SWIM248 0 "register_operand" "=r,r,r")
 	(mult:SWIM248
 	  (match_operand:SWIM248 1 "nonimmediate_operand" "%rm,rm,0")
-	  (match_operand:SWIM248 2 "<general_operand>" "K,<i>,mr")))
+	  (match_operand:SWIM248 2 "<general_operand>" "K,<i>,BMr")))
    (clobber (reg:CC FLAGS_REG))]
   "!(MEM_P (operands[1]) && MEM_P (operands[2]))"
   "@
@@ -8037,7 +8037,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
 	(zero_extend:DI
 	  (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
-		   (match_operand:SI 2 "x86_64_general_operand" "K,e,mr"))))
+		   (match_operand:SI 2 "x86_64_general_operand" "K,e,BMr"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT
    && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
@@ -9711,7 +9711,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI
 	  (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-		  (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+		  (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
   "and{l}\t{%2, %k0|%k0, %2}"
@@ -9721,7 +9721,7 @@ 
 (define_insn "*and<mode>_1"
   [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,Ya,?k")
 	(and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,qm,k")
-		   (match_operand:SWI24 2 "<general_operand>" "r<i>,m,L,k")))
+		   (match_operand:SWI24 2 "<general_operand>" "r<i>,BM,L,k")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (AND, <MODE>mode, operands)"
   "@
@@ -9903,7 +9903,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare (and:SI
 		  (match_operand:SI 1 "nonimmediate_operand" "%0")
-		  (match_operand:SI 2 "x86_64_general_operand" "rme"))
+		  (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
 		 (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
@@ -9946,7 +9946,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare (and:SWI124
 		  (match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
-		  (match_operand:SWI124 2 "<general_operand>" "<r><i>,m"))
+		  (match_operand:SWI124 2 "<general_operand>" "<r><i>,BM"))
 		 (const_int 0)))
    (set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>m,<r>")
 	(and:SWI124 (match_dup 1) (match_dup 2)))]
@@ -10260,7 +10260,7 @@ 
   [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,?k")
 	(any_or:SWI248
 	 (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,k")
-	 (match_operand:SWI248 2 "<general_operand>" "r<i>,m,k")))
+	 (match_operand:SWI248 2 "<general_operand>" "r<i>,BM,k")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
   "@
@@ -10328,7 +10328,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI
 	 (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-		    (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+		    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
   "<logic>{l}\t{%2, %k0|%k0, %2}"
@@ -10431,7 +10431,7 @@ 
   [(set (reg FLAGS_REG)
 	(compare (any_or:SWI
 		  (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
-		  (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+		  (match_operand:SWI 2 "<general_operand>" "<r><i>,BM"))
 		 (const_int 0)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
 	(any_or:SWI (match_dup 1) (match_dup 2)))]
@@ -10446,7 +10446,7 @@ 
 (define_insn "*<code>si_2_zext"
   [(set (reg FLAGS_REG)
 	(compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-			    (match_operand:SI 2 "x86_64_general_operand" "rme"))
+			    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
 		 (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))]
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 770e2f0c0dd..cfc0a50e239 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1199,6 +1199,12 @@ 
   (and (match_operand 0 "memory_operand")
        (not (match_test "x86_extended_reg_mentioned_p (op)"))))
 
+;; Return true if OP is a memory operand representable on ix86.
+(define_predicate "ix86_memory_operand"
+  (and (match_operand 0 "memory_operand")
+       (ior (match_test "mode == QImode || mode == HImode")
+	    (match_operand 0 "x86_64_general_operand"))))
+
 ;; Return true for RTX codes that force SImode address.
 (define_predicate "SImode_address_operand"
   (match_code "subreg,zero_extend,and"))
diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1a.c b/gcc/testsuite/gcc.target/i386/pr103762-1a.c
new file mode 100644
index 00000000000..c9e75bc12d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103762-1a.c
@@ -0,0 +1,647 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+typedef unsigned long int size_t;
+typedef long long int intmax_t;
+typedef unsigned long long int uintmax_t;
+typedef unsigned long long int uint64_t;
+typedef intmax_t tunable_num_t;
+typedef union
+{
+  tunable_num_t numval;
+  const char *strval;
+} tunable_val_t;
+enum
+{
+  HWCAP_X86_SSE2 = 1 << 0,
+  HWCAP_X86_64 = 1 << 1,
+  HWCAP_X86_AVX512_1 = 1 << 2
+};
+typedef void (*tunable_callback_t) (tunable_val_t *);
+extern void *__minimal_malloc (size_t n)
+    __attribute__ ((visibility ("hidden")));
+extern int __libc_enable_secure __attribute__ ((section (".data.rel.ro")));
+extern uint64_t _dl_strtoul (const char *, char **)
+    __attribute__ ((visibility ("hidden")));
+extern void _dl_fatal_printf (const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__));
+typedef enum
+{
+  glibc_rtld_nns,
+  glibc_elision_skip_lock_after_retries,
+  glibc_malloc_trim_threshold,
+  glibc_malloc_perturb,
+  glibc_cpu_x86_shared_cache_size,
+  glibc_pthread_rseq,
+  glibc_mem_tagging,
+  glibc_elision_tries,
+  glibc_elision_enable,
+  glibc_malloc_hugetlb,
+  glibc_cpu_x86_rep_movsb_threshold,
+  glibc_malloc_mxfast,
+  glibc_rtld_dynamic_sort,
+  glibc_elision_skip_lock_busy,
+  glibc_malloc_top_pad,
+  glibc_cpu_x86_rep_stosb_threshold,
+  glibc_cpu_x86_non_temporal_threshold,
+  glibc_cpu_x86_shstk,
+  glibc_pthread_stack_cache_size,
+  glibc_cpu_hwcap_mask,
+  glibc_malloc_mmap_max,
+  glibc_elision_skip_trylock_internal_abort,
+  glibc_malloc_tcache_unsorted_limit,
+  glibc_cpu_x86_ibt,
+  glibc_cpu_hwcaps,
+  glibc_elision_skip_lock_internal_abort,
+  glibc_malloc_arena_max,
+  glibc_malloc_mmap_threshold,
+  glibc_cpu_x86_data_cache_size,
+  glibc_malloc_tcache_count,
+  glibc_malloc_arena_test,
+  glibc_pthread_mutex_spin_count,
+  glibc_rtld_optional_static_tls,
+  glibc_malloc_tcache_max,
+  glibc_malloc_check,
+} tunable_id_t;
+typedef enum
+{
+  TUNABLE_TYPE_INT_32,
+  TUNABLE_TYPE_UINT_64,
+  TUNABLE_TYPE_SIZE_T,
+  TUNABLE_TYPE_STRING
+} tunable_type_code_t;
+typedef struct
+{
+  tunable_type_code_t type_code;
+  tunable_num_t min;
+  tunable_num_t max;
+} tunable_type_t;
+typedef enum
+{
+  TUNABLE_SECLEVEL_SXID_ERASE = 0,
+  TUNABLE_SECLEVEL_SXID_IGNORE = 1,
+  TUNABLE_SECLEVEL_NONE = 2,
+} tunable_seclevel_t;
+struct _tunable
+{
+  const char name[42];
+  tunable_type_t type;
+  tunable_val_t val;
+  _Bool initialized;
+  tunable_seclevel_t security_level;
+  const char env_alias[23];
+};
+typedef struct _tunable tunable_t;
+extern _Bool unsigned_tunable_type (tunable_type_code_t t);
+
+static tunable_t tunable_list[] __attribute__ ((section (".data.rel.ro"))) = {
+  { "glibc"
+    "."
+    "rtld"
+    "."
+    "nns",
+    { TUNABLE_TYPE_SIZE_T, 1, 16 },
+    { .numval = 4 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "skip_lock_after_retries",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    { .numval = 3 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "trim_threshold",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_TRIM_THRESHOLD_" },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "perturb",
+    { TUNABLE_TYPE_INT_32, 0, 0xff },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_PERTURB_" },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_shared_cache_size",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "pthread"
+    "."
+    "rseq",
+    { TUNABLE_TYPE_INT_32, 0, 1 },
+    { .numval = 1 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "mem"
+    "."
+    "tagging",
+    { TUNABLE_TYPE_INT_32, 0, 255 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    { 0 } },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "tries",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    { .numval = 3 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "enable",
+    { TUNABLE_TYPE_INT_32, 0, 1 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "hugetlb",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_rep_movsb_threshold",
+    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "mxfast",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    { 0 } },
+  { "glibc"
+    "."
+    "rtld"
+    "."
+    "dynamic_sort",
+    { TUNABLE_TYPE_INT_32, 1, 2 },
+    { .numval = 2 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "skip_lock_busy",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    { .numval = 3 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "top_pad",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_TOP_PAD_" },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_rep_stosb_threshold",
+    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+    { .numval = 2048 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_non_temporal_threshold",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_shstk",
+    { TUNABLE_TYPE_STRING, 0, 0 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "pthread"
+    "."
+    "stack_cache_size",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    { .numval = 41943040 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "hwcap_mask",
+    { TUNABLE_TYPE_UINT_64, 0, (18446744073709551615UL) },
+    { .numval = (HWCAP_X86_64 | HWCAP_X86_AVX512_1) },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    "LD_HWCAP_MASK" },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "mmap_max",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_MMAP_MAX_" },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "skip_trylock_internal_abort",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    { .numval = 3 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "tcache_unsorted_limit",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_ibt",
+    { TUNABLE_TYPE_STRING, 0, 0 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "hwcaps",
+    { TUNABLE_TYPE_STRING, 0, 0 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "elision"
+    "."
+    "skip_lock_internal_abort",
+    { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+    { .numval = 3 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "arena_max",
+    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_ARENA_MAX" },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "mmap_threshold",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_MMAP_THRESHOLD_" },
+  { "glibc"
+    "."
+    "cpu"
+    "."
+    "x86_data_cache_size",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "tcache_count",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "arena_test",
+    { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_IGNORE,
+    "MALLOC_ARENA_TEST" },
+  { "glibc"
+    "."
+    "pthread"
+    "."
+    "mutex_spin_count",
+    { TUNABLE_TYPE_INT_32, 0, 32767 },
+    { .numval = 100 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "rtld"
+    "."
+    "optional_static_tls",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    { .numval = 512 },
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "tcache_max",
+    { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    { 0 } },
+  { "glibc"
+    "."
+    "malloc"
+    "."
+    "check",
+    { TUNABLE_TYPE_INT_32, 0, 3 },
+    {},
+    ((void *)0),
+    TUNABLE_SECLEVEL_SXID_ERASE,
+    "MALLOC_CHECK_" },
+};
+extern void __tunables_init (char **);
+extern void __tunables_print (void);
+extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
+extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
+                               tunable_num_t *);
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_val_lt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
+{
+  if (unsigned_cmp)
+    return (uintmax_t)lhs < (uintmax_t)rhs;
+  else
+    return lhs < rhs;
+}
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_val_gt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
+{
+  if (unsigned_cmp)
+    return (uintmax_t)lhs > (uintmax_t)rhs;
+  else
+    return lhs > rhs;
+}
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_is_name (const char *orig, const char *envname)
+{
+  for (; *orig != '\0' && *envname != '\0'; envname++, orig++)
+    if (*orig != *envname)
+      break;
+  if (*orig == '\0' && *envname == '=')
+    return 1;
+  else
+    return 0;
+}
+static char *
+tunables_strdup (const char *in)
+{
+  size_t i = 0;
+  while (in[i++] != '\0')
+    ;
+  char *out = __minimal_malloc (i + 1);
+  if (out == ((void *)0))
+    _dl_fatal_printf ("failed to allocate memory to process tunables\n");
+  while (i-- > 0)
+    out[i] = in[i];
+  return out;
+}
+static char **
+get_next_env (char **envp, char **name, size_t *namelen, char **val,
+              char ***prev_envp)
+{
+  while (envp != ((void *)0) && *envp != ((void *)0))
+    {
+      char **prev = envp;
+      char *envline = *envp++;
+      int len = 0;
+      while (envline[len] != '\0' && envline[len] != '=')
+        len++;
+      if (envline[len] == '\0')
+        continue;
+      *name = envline;
+      *namelen = len;
+      *val = &envline[len + 1];
+      *prev_envp = prev;
+      return envp;
+    }
+  return ((void *)0);
+}
+static void
+do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
+                       const tunable_num_t *minp, const tunable_num_t *maxp)
+{
+  tunable_num_t val, min, max;
+  if (cur->type.type_code == TUNABLE_TYPE_STRING)
+    {
+      cur->val.strval = valp->strval;
+      cur->initialized = 1;
+      return;
+    }
+  _Bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
+  val = valp->numval;
+  min = minp != ((void *)0) ? *minp : cur->type.min;
+  max = maxp != ((void *)0) ? *maxp : cur->type.max;
+  if (tunable_val_lt (min, cur->type.min, unsigned_cmp))
+    min = cur->type.min;
+  if (tunable_val_gt (max, cur->type.max, unsigned_cmp))
+    max = cur->type.max;
+  if (tunable_val_gt (min, max, unsigned_cmp))
+    {
+      min = cur->type.min;
+      max = cur->type.max;
+    }
+  if (tunable_val_lt (val, min, unsigned_cmp)
+      || tunable_val_lt (max, val, unsigned_cmp))
+    return;
+  cur->val.numval = val;
+  cur->type.min = min;
+  cur->type.max = max;
+  cur->initialized = 1;
+}
+static void
+tunable_initialize (tunable_t *cur, const char *strval)
+{
+  tunable_val_t val;
+  if (cur->type.type_code != TUNABLE_TYPE_STRING)
+    val.numval = (tunable_num_t)_dl_strtoul (strval, ((void *)0));
+  else
+    val.strval = strval;
+  do_tunable_update_val (cur, &val, ((void *)0), ((void *)0));
+}
+static void
+parse_tunables (char *tunestr, char *valstring)
+{
+  if (tunestr == ((void *)0) || *tunestr == '\0')
+    return;
+  char *p = tunestr;
+  size_t off = 0;
+  while (1)
+    {
+      char *name = p;
+      size_t len = 0;
+      while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
+        len++;
+      if (p[len] == '\0')
+        {
+          if (__libc_enable_secure)
+            tunestr[off] = '\0';
+          return;
+        }
+      if (p[len] == ':')
+        {
+          p += len + 1;
+          continue;
+        }
+      p += len + 1;
+      char *value = &valstring[p - tunestr];
+      len = 0;
+      while (p[len] != ':' && p[len] != '\0')
+        len++;
+      for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+        {
+          tunable_t *cur = &tunable_list[i];
+          if (tunable_is_name (cur->name, name))
+            {
+              if (__libc_enable_secure)
+                {
+                  if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
+                    {
+                      if (off > 0)
+                        tunestr[off++] = ':';
+                      const char *n = cur->name;
+                      while (*n != '\0')
+                        tunestr[off++] = *n++;
+                      tunestr[off++] = '=';
+                      for (size_t j = 0; j < len; j++)
+                        tunestr[off++] = value[j];
+                    }
+                  if (cur->security_level != TUNABLE_SECLEVEL_NONE)
+                    break;
+                }
+              value[len] = '\0';
+              tunable_initialize (cur, value);
+              break;
+            }
+        }
+      if (p[len] != '\0')
+        p += len + 1;
+    }
+}
+void
+__tunables_init (char **envp)
+{
+  char *envname = ((void *)0);
+  char *envval = ((void *)0);
+  size_t len = 0;
+  char **prev_envp = envp;
+  while ((envp = get_next_env (envp, &envname, &len, &envval, &prev_envp))
+         != ((void *)0))
+    {
+      if (tunable_is_name ("GLIBC_TUNABLES", envname))
+        {
+          char *new_env = tunables_strdup (envname);
+          if (new_env != ((void *)0))
+            parse_tunables (new_env + len + 1, envval);
+          *prev_envp = new_env;
+          continue;
+        }
+      for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+        {
+          tunable_t *cur = &tunable_list[i];
+          const char *name = cur->env_alias;
+          if (tunable_is_name (name, envname))
+            {
+              tunable_initialize (cur, envval);
+              break;
+            }
+        }
+    }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1b.c b/gcc/testsuite/gcc.target/i386/pr103762-1b.c
new file mode 100644
index 00000000000..391f51cf7f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103762-1b.c
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpie" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+#include "pr103762-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr103762-1c.c b/gcc/testsuite/gcc.target/i386/pr103762-1c.c
new file mode 100644
index 00000000000..4667b06c171
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103762-1c.c
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpic" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+#include "pr103762-1a.c"