aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Greenhalgh <james.greenhalgh@arm.com>2014-05-16 09:01:28 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2014-05-16 09:01:28 +0000
commitb1685e6274a141a05050c9734b974732a5019f4a (patch)
tree68b09a7214a34cd4e6939ea2d72daeb1bdc5c4d7
parent268c3b4758fd7fc54f8cc8220f0a6193ed862a42 (diff)
downloadgcc-b1685e6274a141a05050c9734b974732a5019f4a.zip
gcc-b1685e6274a141a05050c9734b974732a5019f4a.tar.gz
gcc-b1685e6274a141a05050c9734b974732a5019f4a.tar.bz2
[AArch64 costs 10/18] Improve costs for sign/zero extend operations
gcc/ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost ZERO_EXTEND and SIGN_EXTEND better. Co-Authored-By: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> From-SVN: r210502
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/aarch64/aarch64.c53
2 files changed, 53 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e648140..38a66e7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,12 @@
2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost
+ ZERO_EXTEND and SIGN_EXTEND better.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
* config/aarch64/aarch64.c (aarch64_rtx_costs): Improve cost for
logical operations.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6b20d4a..76ef7ce 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -5281,21 +5281,62 @@ cost_minus:
return false;
case ZERO_EXTEND:
- if ((GET_MODE (x) == DImode
- && GET_MODE (XEXP (x, 0)) == SImode)
- || GET_CODE (XEXP (x, 0)) == MEM)
+
+ op0 = XEXP (x, 0);
+ /* If a value is written in SI mode, then zero extended to DI
+ mode, the operation will in general be free as a write to
+ a 'w' register implicitly zeroes the upper bits of an 'x'
+ register. However, if this is
+
+ (set (reg) (zero_extend (reg)))
+
+ we must cost the explicit register move. */
+ if (mode == DImode
+ && GET_MODE (op0) == SImode
+ && outer == SET)
+ {
+ int op_cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+
+ if (!op_cost && speed)
+ /* MOV. */
+ *cost += extra_cost->alu.extend;
+ else
+ /* Free, the cost is that of the SI mode operation. */
+ *cost = op_cost;
+
+ return true;
+ }
+ else if (MEM_P (XEXP (x, 0)))
{
- *cost += rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+ /* All loads can zero extend to any size for free. */
+ *cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, param, speed);
return true;
}
+
+ /* UXTB/UXTH. */
+ if (speed)
+ *cost += extra_cost->alu.extend;
+
return false;
case SIGN_EXTEND:
- if (GET_CODE (XEXP (x, 0)) == MEM)
+ if (MEM_P (XEXP (x, 0)))
{
- *cost += rtx_cost (XEXP (x, 0), SIGN_EXTEND, 0, speed);
+ /* LDRSH. */
+ if (speed)
+ {
+ rtx address = XEXP (XEXP (x, 0), 0);
+ *cost += extra_cost->ldst.load_sign_extend;
+
+ *cost +=
+ COSTS_N_INSNS (aarch64_address_cost (address, mode,
+ 0, speed));
+ }
return true;
}
+
+ if (speed)
+ *cost += extra_cost->alu.extend;
return false;
case ROTATE: