NDD uses evex prefix, so when segment prefix is also applied, the instruction could excceed its 15byte limit, especially adding immediates. This could happen when "e" constraint accepts any UNSPEC_TPOFF/UNSPEC_NTPOFF constant and it will add the offset to segment register, which will be encoded using segment prefix. Disable those *POFF constant usage in NDD add alternatives with new constraint.
gcc/ChangeLog: * config/i386/constraints.md (je): New constraint. * config/i386/i386-protos.h (x86_no_poff_operand_p): New function to check any *POFF constant. * config/i386/i386.cc (x86_no_poff_operand_p): New prototype. * config/i386/i386.md (*add<mode>_1): Split out je alternative for add. --- gcc/config/i386/constraints.md | 5 +++++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.cc | 25 +++++++++++++++++++++++++ gcc/config/i386/i386.md | 10 +++++----- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index cbee31fa40a..c6b51324294 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -433,3 +433,8 @@ (define_address_constraint "jb" (define_register_constraint "jc" "TARGET_APX_EGPR && !TARGET_AVX ? GENERAL_GPR16 : GENERAL_REGS") + +(define_constraint "je" + "@internal constant that do not allow any unspec global offsets" + (and (match_operand 0 "x86_64_immediate_operand") + (match_test "x86_no_poff_operand_p (op)"))) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 3e08eae4e79..5d902e2925b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -66,6 +66,7 @@ extern bool x86_extended_QIreg_mentioned_p (rtx_insn *); extern bool x86_extended_reg_mentioned_p (rtx); extern bool x86_extended_rex2reg_mentioned_p (rtx); extern bool x86_evex_reg_mentioned_p (rtx [], int); +extern bool x86_no_poff_operand_p (rtx); extern bool x86_maybe_negate_const_int (rtx *, machine_mode); extern machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 3779d5b1206..47159b06f7d 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -23292,6 +23292,31 @@ x86_evex_reg_mentioned_p (rtx operands[], int nops) return false; } +/* Return true when rtx operand does not contain any UNSPEC_*POFF related + constant to avoid APX_NDD instructions excceed encoding length limit. */ +bool +x86_no_poff_operand_p (rtx operand) +{ + if (GET_CODE (operand) == CONST) + { + rtx op = XEXP (operand, 0); + if (GET_CODE (op) == PLUS) + op = XEXP (op, 0); + + if (GET_CODE (op) == UNSPEC) + { + int unspec = XINT (op, 1); + return (unspec != UNSPEC_NTPOFF + && unspec != UNSPEC_TPOFF + && unspec != UNSPEC_DTPOFF + && unspec != UNSPEC_GOTTPOFF + && unspec != UNSPEC_GOTNTPOFF + && unspec != UNSPEC_INDNTPOFF); + } + } + return true; +} + /* If profitable, negate (without causing overflow) integer constant of mode MODE at location LOC. Return true in this case. */ bool diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7ddb2cb2a71..ecd06625a7d 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6359,15 +6359,15 @@ (define_insn_and_split "*add<dwi>3_doubleword_concat_zext" "split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[5]);") (define_insn "*add<mode>_1" - [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r") + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r,r") (plus:SWI48 - (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rm,r") - (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,re,BM"))) + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rm,r,m,r") + (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,je,BM"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, ix86_can_use_ndd_p (PLUS))" { - bool use_ndd = (which_alternative == 4 || which_alternative == 5); + bool use_ndd = (which_alternative >= 4); switch (get_attr_type (insn)) { case TYPE_LEA: @@ -6398,7 +6398,7 @@ (define_insn "*add<mode>_1" : "add{<imodesuffix>}\t{%2, %0|%0, %2}"; } } - [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd") (set (attr "type") (cond [(eq_attr "alternative" "3") (const_string "lea") -- 2.31.1