return n;
} /* transform_node_End */
+/** returns 1 if a == -b */
+static int is_negated_value(ir_node *a, ir_node *b) {
+ if(is_Minus(a) && get_Minus_op(a) == b)
+ return 1;
+ if(is_Minus(b) && get_Minus_op(b) == a)
+ return 1;
+ if(is_Sub(a) && is_Sub(b)) {
+ ir_node *a_left = get_Sub_left(a);
+ ir_node *a_right = get_Sub_right(a);
+ ir_node *b_left = get_Sub_left(b);
+ ir_node *b_right = get_Sub_right(b);
+
+ if(a_left == b_right && a_right == b_left)
+ return 1;
+ }
+
+ return 0;
+}
+
/**
* Optimize a Mux into some simpler cases.
*/
if (get_irn_op(sel) == op_Proj && !mode_honor_signed_zeros(mode)) {
ir_node *cmp = get_Proj_pred(sel);
- long proj_nr = get_Proj_proj(sel);
- ir_node *f = get_Mux_false(n);
+ long pn = get_Proj_proj(sel);
+ ir_node *f = get_Mux_false(n);
ir_node *t = get_Mux_true(n);
- if (get_irn_op(cmp) == op_Cmp && classify_Const(get_Cmp_right(cmp)) == CNST_NULL) {
- ir_node *block = get_irn_n(n, -1);
-
- /*
- * Note: normalization puts the constant on the right site,
- * so we check only one case.
- *
- * Note further that these optimization work even for floating point
- * with NaN's because -NaN == NaN.
- * However, if +0 and -0 is handled differently, we cannot use the first one.
- */
- if (get_irn_op(f) == op_Minus &&
- get_Minus_op(f) == t &&
- get_Cmp_left(cmp) == t) {
-
- if (proj_nr == pn_Cmp_Ge || proj_nr == pn_Cmp_Gt) {
- /* Mux(a >=/> 0, -a, a) ==> Abs(a) */
- n = new_rd_Abs(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- t, mode);
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
- return n;
- } else if (proj_nr == pn_Cmp_Le || proj_nr == pn_Cmp_Lt) {
- /* Mux(a <=/< 0, -a, a) ==> Minus(Abs(a)) */
- n = new_rd_Abs(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- t, mode);
- n = new_rd_Minus(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- n, mode);
-
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
- return n;
- }
- } else if (get_irn_op(t) == op_Minus &&
- get_Minus_op(t) == f &&
- get_Cmp_left(cmp) == f) {
-
- if (proj_nr == pn_Cmp_Le || proj_nr == pn_Cmp_Lt) {
- /* Mux(a <=/< 0, a, -a) ==> Abs(a) */
- n = new_rd_Abs(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- f, mode);
+ /*
+ * Note: normalization puts the constant on the right site,
+ * so we check only one case.
+ *
+ * Note further that these optimization work even for floating point
+ * with NaN's because -NaN == NaN.
+ * However, if +0 and -0 is handled differently, we cannot use the first
+ * one.
+ */
+ if (get_irn_op(cmp) == op_Cmp
+ && classify_Const(get_Cmp_right(cmp)) == CNST_NULL) {
+ ir_node *block = get_irn_n(n, -1);
+
+ if(is_negated_value(f, t)) {
+ ir_node *cmp_left = get_Cmp_left(cmp);
+
+ /* Psi(a >= 0, a, -a) = Psi(a <= 0, -a, a) ==> Abs(a) */
+ if ( (cmp_left == t && (pn == pn_Cmp_Ge || pn == pn_Cmp_Gt))
+ || (cmp_left == f && (pn == pn_Cmp_Le || pn == pn_Cmp_Lt)))
+ {
+ n = new_rd_Abs(get_irn_dbg_info(n), current_ir_graph, block,
+ cmp_left, mode);
DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
return n;
- } else if (proj_nr == pn_Cmp_Ge || proj_nr == pn_Cmp_Gt) {
- /* Mux(a >=/> 0, a, -a) ==> Minus(Abs(a)) */
- n = new_rd_Abs(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- f, mode);
- n = new_rd_Minus(get_irn_dbg_info(n),
- current_ir_graph,
- block,
- n, mode);
-
+ /* Psi(a <= 0, a, -a) = Psi(a >= 0, -a, a) ==> -Abs(a) */
+ } else if ((cmp_left == t && (pn == pn_Cmp_Le || pn == pn_Cmp_Lt))
+ || (cmp_left == f && (pn == pn_Cmp_Ge || pn == pn_Cmp_Gt)))
+ {
+ n = new_rd_Abs(get_irn_dbg_info(n), current_ir_graph, block,
+ cmp_left, mode);
+ n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph,
+ block, n, mode);
DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
return n;
}
* work if mode(x) = Hs and mode == Is, but at least it removes
* all wrong cases.
*/
- if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Le) &&
+ if ((pn == pn_Cmp_Lt || pn == pn_Cmp_Le) &&
classify_Const(t) == CNST_ALL_ONE &&
classify_Const(f) == CNST_NULL) {
/*
mode);
DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_SHR);
return n;
- } else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Ge) &&
+ } else if ((pn == pn_Cmp_Gt || pn == pn_Cmp_Ge) &&
classify_Const(t) == CNST_ONE &&
classify_Const(f) == CNST_NULL) {
/*