From 31ed166586451e3955d0da9c7931c71da968eee4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 3 May 2016 13:45:04 +0200 Subject: [PATCH] re PR rtl-optimization/70467 (Useless "and [esp],-1" emitted on AND with uint64_t variable) PR rtl-optimization/70467 * config/i386/predicates.md (x86_64_hilo_int_operand, x86_64_hilo_general_operand): New predicates. * config/i386/constraints.md (Wd): New constraint. * config/i386/i386.md (mode attr di): Use Wd instead of e. (general_hilo_operand): New mode attr. (add3, sub3): Use instead of . (*add3_doubleword, *sub3_doubleword): Use x86_64_hilo_general_operand instead of . * gcc.target/i386/pr70467-3.c: New test. * gcc.target/i386/pr70467-4.c: New test. Co-Authored-By: Uros Bizjak From-SVN: r235816 --- gcc/ChangeLog | 14 ++++++++++ gcc/config/i386/constraints.md | 5 ++++ gcc/config/i386/i386.md | 21 +++++++++++---- gcc/config/i386/predicates.md | 31 +++++++++++++++++++++++ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.target/i386/pr70467-3.c | 19 ++++++++++++++ gcc/testsuite/gcc.target/i386/pr70467-4.c | 18 +++++++++++++ 7 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr70467-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr70467-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2952eb9625..9b1b95b5fff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2016-05-03 Jakub Jelinek + Uros Bizjak + + PR rtl-optimization/70467 + * config/i386/predicates.md (x86_64_hilo_int_operand, + x86_64_hilo_general_operand): New predicates. + * config/i386/constraints.md (Wd): New constraint. + * config/i386/i386.md (mode attr di): Use Wd instead of e. + (general_hilo_operand): New mode attr. + (add3, sub3): Use + instead of . + (*add3_doubleword, *sub3_doubleword): Use + x86_64_hilo_general_operand instead of . + 2016-05-03 Jakub Jelinek PR tree-optimization/70916 diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 93d136bc666..ccebee775e1 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -270,6 +270,11 @@ (and (match_operand 0 "x86_64_zext_immediate_operand") (match_test "GET_MODE (op) != VOIDmode"))) +(define_constraint "Wd" + "128-bit integer constant where both the high and low 64-bit word + of it satisfies the e constraint." + (match_operand 0 "x86_64_hilo_int_operand")) + (define_constraint "Z" "32-bit unsigned integer constant, or a symbolic reference known to fit that range (for immediate operands in zero-extending x86-64 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c409872a0be..940dc204be5 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1065,7 +1065,7 @@ (define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")]) ;; Immediate operand constraint for double integer modes. -(define_mode_attr di [(SI "nF") (DI "e")]) +(define_mode_attr di [(SI "nF") (DI "Wd")]) ;; Immediate operand constraint for shifts. (define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")]) @@ -1078,6 +1078,15 @@ (DI "x86_64_general_operand") (TI "x86_64_general_operand")]) +;; General operand predicate for integer modes, where for TImode +;; we need both words of the operand to be general operands. +(define_mode_attr general_hilo_operand + [(QI "general_operand") + (HI "general_operand") + (SI "x86_64_general_operand") + (DI "x86_64_general_operand") + (TI "x86_64_hilo_general_operand")]) + ;; General sign extend operand predicate for integer modes, ;; which disallows VOIDmode operands and thus it is suitable ;; for use inside sign_extend. @@ -5433,7 +5442,7 @@ (define_expand "add3" [(set (match_operand:SDWIM 0 "nonimmediate_operand") (plus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand") - (match_operand:SDWIM 2 "")))] + (match_operand:SDWIM 2 "")))] "" "ix86_expand_binary_operator (PLUS, mode, operands); DONE;") @@ -5441,7 +5450,8 @@ [(set (match_operand: 0 "nonimmediate_operand" "=r,o") (plus: (match_operand: 1 "nonimmediate_operand" "%0,0") - (match_operand: 2 "" "ro,r"))) + (match_operand: 2 "x86_64_hilo_general_operand" + "ro,r"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, mode, operands)" "#" @@ -6345,7 +6355,7 @@ (define_expand "sub3" [(set (match_operand:SDWIM 0 "nonimmediate_operand") (minus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand") - (match_operand:SDWIM 2 "")))] + (match_operand:SDWIM 2 "")))] "" "ix86_expand_binary_operator (MINUS, mode, operands); DONE;") @@ -6353,7 +6363,8 @@ [(set (match_operand: 0 "nonimmediate_operand" "=r,o") (minus: (match_operand: 1 "nonimmediate_operand" "0,0") - (match_operand: 2 "" "ro,r"))) + (match_operand: 2 "x86_64_hilo_general_operand" + "ro,r"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, mode, operands)" "#" diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index c1541b56d13..b3a471d8b76 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -342,6 +342,29 @@ return false; }) +;; Return true if VALUE is a constant integer whose low and high words satisfy +;; x86_64_immediate_operand. +(define_predicate "x86_64_hilo_int_operand" + (match_code "const_int,const_wide_int") +{ + switch (GET_CODE (op)) + { + case CONST_INT: + return x86_64_immediate_operand (op, mode); + + case CONST_WIDE_INT: + gcc_assert (CONST_WIDE_INT_NUNITS (op) == 2); + return (x86_64_immediate_operand (GEN_INT (CONST_WIDE_INT_ELT (op, 0)), + DImode) + && x86_64_immediate_operand (GEN_INT (CONST_WIDE_INT_ELT (op, + 1)), + DImode)); + + default: + gcc_unreachable (); + } +}) + ;; Return true if size of VALUE can be stored in a sign ;; extended immediate field. (define_predicate "x86_64_immediate_size_operand" @@ -357,6 +380,14 @@ (match_operand 0 "x86_64_immediate_operand")) (match_operand 0 "general_operand"))) +;; Return true if OP's both words are general operands representable +;; on x86_64. +(define_predicate "x86_64_hilo_general_operand" + (if_then_else (match_test "TARGET_64BIT") + (ior (match_operand 0 "nonimmediate_operand") + (match_operand 0 "x86_64_hilo_int_operand")) + (match_operand 0 "general_operand"))) + ;; Return true if OP is non-VOIDmode general operand representable ;; on x86_64. This predicate is used in sign-extending conversion ;; operations that require non-VOIDmode immediate operands. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0941f39afa5..7a898688fc5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2016-05-03 Jakub Jelinek + PR rtl-optimization/70467 + * gcc.target/i386/pr70467-3.c: New test. + * gcc.target/i386/pr70467-4.c: New test. + PR tree-optimization/70916 * gcc.c-torture/compile/pr70916.c: New test. diff --git a/gcc/testsuite/gcc.target/i386/pr70467-3.c b/gcc/testsuite/gcc.target/i386/pr70467-3.c new file mode 100644 index 00000000000..4d2a6cfaead --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr70467-3.c @@ -0,0 +1,19 @@ +/* PR rtl-optimization/70467 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2" } */ + +__uint128_t +foo (__uint128_t x) +{ + return x + ((__uint128_t) 123456 << 64); +} + +__uint128_t +bar (__uint128_t x) +{ + return x - ((__uint128_t) 123456 << 64); +} + +/* Make sure there are no unnecessary additions with carry. */ +/* { dg-final { scan-assembler-not "adcq\[^\n\r\]*%" } } */ +/* { dg-final { scan-assembler-not "sbbq\[^\n\r\]*%" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr70467-4.c b/gcc/testsuite/gcc.target/i386/pr70467-4.c new file mode 100644 index 00000000000..91f9b6f43c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr70467-4.c @@ -0,0 +1,18 @@ +/* PR rtl-optimization/70467 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2" } */ + +__uint128_t +foo (__uint128_t x) +{ + return x + ((__uint128_t) 123456 << 64) + 0x1234567; +} + +__uint128_t +bar (__uint128_t x) +{ + return x - ((__uint128_t) 123456 << 64) + 0x1234567; +} + +/* Make sure the immediates are not loaded into registers first. */ +/* { dg-final { scan-assembler-not "mov\[lq\]\[ \t\]*.\[0-9-\]" } } */ -- 2.30.2