diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2022-05-23 08:47:42 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2022-05-23 08:47:42 +0100 |
commit | 7707d7fddf7d6858399c8a47b139dc4708c5d7d9 (patch) | |
tree | a426ea691f3525546d8b5bd081ddeca1b59ad1d7 | |
parent | 075fb873c264a030f56793cb162c9fdecbdd1773 (diff) | |
download | gcc-7707d7fddf7d6858399c8a47b139dc4708c5d7d9.zip gcc-7707d7fddf7d6858399c8a47b139dc4708c5d7d9.tar.gz gcc-7707d7fddf7d6858399c8a47b139dc4708c5d7d9.tar.bz2 |
Some additional ix86_rtx_costs clean-ups: NEG, AND, andn and pandn.
Double-word NOT requires two operations, but double-word NEG requires
three operations. Using SSE, vector NOT requires a pxor with -1, but
AND of NOT is cheap thanks to the existence of pandn. There's also some
legacy (aka incorrect) logic explicitly testing for DImode [independently
of TARGET_64BIT] in determining the cost of logic operations that's not
required.
2022-05-23 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/i386/i386.cc (ix86_rtx_costs) <case AND>: Split from
XOR/IOR case. Account for two instructions for double-word
operations. In case of vector pandn, account for single
instruction. Likewise for integer andn with TARGET_BMI.
<case NOT>: Vector NOT requires more than 1 instruction (pxor).
<case NEG>: Double-word negation requires 3 instructions.
-rw-r--r-- | gcc/config/i386/i386.cc | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 30a9cd0..daa60ac 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -20738,70 +20738,125 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, } if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode)) - { - *total = cost->addss; - return false; - } + *total = cost->addss; else if (X87_FLOAT_MODE_P (mode)) - { - *total = cost->fadd; - return false; - } + *total = cost->fadd; else if (FLOAT_MODE_P (mode)) - { - *total = ix86_vec_cost (mode, cost->addss); - return false; - } - /* FALLTHRU */ + *total = ix86_vec_cost (mode, cost->addss); + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + *total = ix86_vec_cost (mode, cost->sse_op); + else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + *total = cost->add * 2; + else + *total = cost->add; + return false; - case AND: case IOR: case XOR: - if (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) > UNITS_PER_WORD) + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + *total = ix86_vec_cost (mode, cost->sse_op); + else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + *total = cost->add * 2; + else + *total = cost->add; + return false; + + case AND: + if (address_no_seg_operand (x, mode)) { - *total = (cost->add * 2 - + (rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed) - << (GET_MODE (XEXP (x, 0)) != DImode)) - + (rtx_cost (XEXP (x, 1), mode, outer_code, opno, speed) - << (GET_MODE (XEXP (x, 1)) != DImode))); + *total = cost->lea; return true; } - else if (code == AND - && address_no_seg_operand (x, mode)) + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) { - *total = cost->lea; - return true; + /* pandn is a single instruction. */ + if (GET_CODE (XEXP (x, 0)) == NOT) + { + *total = ix86_vec_cost (mode, cost->sse_op) + + rtx_cost (XEXP (XEXP (x, 0), 0), mode, + outer_code, opno, speed) + + rtx_cost (XEXP (x, 1), mode, + outer_code, opno, speed); + return true; + } + else if (GET_CODE (XEXP (x, 1)) == NOT) + { + *total = ix86_vec_cost (mode, cost->sse_op) + + rtx_cost (XEXP (x, 0), mode, + outer_code, opno, speed) + + rtx_cost (XEXP (XEXP (x, 1), 0), mode, + outer_code, opno, speed); + return true; + } + *total = ix86_vec_cost (mode, cost->sse_op); } - /* FALLTHRU */ - - case NEG: - if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode)) + else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) { - *total = cost->sse_op; - return false; + if (TARGET_BMI && GET_CODE (XEXP (x,0)) == NOT) + { + *total = cost->add * 2 + + rtx_cost (XEXP (XEXP (x, 0), 0), mode, + outer_code, opno, speed) + + rtx_cost (XEXP (x, 1), mode, + outer_code, opno, speed); + return true; + } + else if (TARGET_BMI && GET_CODE (XEXP (x, 1)) == NOT) + { + *total = cost->add * 2 + + rtx_cost (XEXP (x, 0), mode, + outer_code, opno, speed) + + rtx_cost (XEXP (XEXP (x, 1), 0), mode, + outer_code, opno, speed); + return true; + } + *total = cost->add * 2; } - else if (X87_FLOAT_MODE_P (mode)) + else if (TARGET_BMI && GET_CODE (XEXP (x,0)) == NOT) { - *total = cost->fchs; - return false; + *total = cost->add + + rtx_cost (XEXP (XEXP (x, 0), 0), mode, + outer_code, opno, speed) + + rtx_cost (XEXP (x, 1), mode, outer_code, opno, speed); + return true; } - else if (FLOAT_MODE_P (mode)) + else if (TARGET_BMI && GET_CODE (XEXP (x,1)) == NOT) { - *total = ix86_vec_cost (mode, cost->sse_op); - return false; + *total = cost->add + + rtx_cost (XEXP (x, 0), mode, outer_code, opno, speed) + + rtx_cost (XEXP (XEXP (x, 1), 0), mode, + outer_code, opno, speed); + return true; } - /* FALLTHRU */ + else + *total = cost->add; + return false; case NOT: if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) - *total = ix86_vec_cost (mode, cost->sse_op); + // vnot is pxor -1. + *total = ix86_vec_cost (mode, cost->sse_op) + 1; else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) *total = cost->add * 2; else *total = cost->add; return false; + case NEG: + if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode)) + *total = cost->sse_op; + else if (X87_FLOAT_MODE_P (mode)) + *total = cost->fchs; + else if (FLOAT_MODE_P (mode)) + *total = ix86_vec_cost (mode, cost->sse_op); + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + *total = ix86_vec_cost (mode, cost->sse_op); + else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + *total = cost->add * 3; + else + *total = cost->add; + return false; + case COMPARE: rtx op0, op1; op0 = XEXP (x, 0); |