summaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/aarch64/aarch64.c')
-rw-r--r--gcc/config/aarch64/aarch64.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3fd58b96104..9e507b84257 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3326,17 +3326,24 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
|| GET_CODE (x) == NEG))
return CC_NZmode;
- /* A compare with a shifted or negated operand. Because of canonicalization,
+ /* A compare with a shifted operand. Because of canonicalization,
the comparison will have to be swapped when we emit the assembly
code. */
if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
&& (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)
&& (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
|| GET_CODE (x) == LSHIFTRT
- || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND
- || GET_CODE (x) == NEG))
+ || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND))
return CC_SWPmode;
+ /* Similarly for a negated operand, but we can only do this for
+ equalities. */
+ if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
+ && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)
+ && (code == EQ || code == NE)
+ && GET_CODE (x) == NEG)
+ return CC_Zmode;
+
/* A compare of a mode narrower than SI mode against zero can be done
by extending the value in the comparison. */
if ((GET_MODE (x) == QImode || GET_MODE (x) == HImode)
@@ -3427,6 +3434,15 @@ aarch64_get_condition_code (rtx x)
}
break;
+ case CC_Zmode:
+ switch (comp_code)
+ {
+ case NE: return AARCH64_NE;
+ case EQ: return AARCH64_EQ;
+ default: gcc_unreachable ();
+ }
+ break;
+
default:
gcc_unreachable ();
break;
@@ -4643,12 +4659,15 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
extra_cost->mult[GET_MODE (x) == DImode].extend_add;
return true;
}
+
*cost += (rtx_cost (XEXP (op0, 0), MULT, 0, speed)
+ rtx_cost (XEXP (op0, 1), MULT, 1, speed)
+ rtx_cost (op1, PLUS, 1, speed));
if (speed)
*cost += extra_cost->mult[GET_MODE (x) == DImode].add;
+
+ return true;
}
*cost += (rtx_cost (new_op0, PLUS, 0, speed)