ix86: Don't match the 'm' constraint on x86_64_general_operand
Commit Message
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
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
>
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
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")])
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
@@ -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."
@@ -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))))]
@@ -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"))
new file mode 100644
@@ -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;
+ }
+ }
+ }
+}
new file mode 100644
@@ -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"
new file mode 100644
@@ -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"