diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c new file mode 100644 index 00000000000..4b94203b0d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + + +int min1(int a, int b) +{ + if (a <= b) + return a < b ? a : b; + return 0; +} + +int min2(int a, int b) +{ + if (a <= b) + return a > b ? b : a; + return 0; +} + +int min3(int a, int b) +{ + if (a < b) + return a < b ? a : b; + return 0; +} + +int min4(int a, int b) +{ + if (a < b) + return a > b ? b : a; + return 0; +} + +int min5(int a, int b) +{ + if (a <= b) + return a <= b ? a : b; + return 0; +} + +int min6(int a, int b) +{ + if (a <= b) + return a >= b ? b : a; + return 0; +} + +int min7(int a, int b) +{ + if (a < b) + return a <= b ? a : b; + return 0; +} + +int min8(int a, int b) +{ + if (b > a) + return a >= b ? b : a; + return 0; +} + +int min9(int a, int b) +{ + if (b >= a) + return a < b ? a : b; + return 0; +} + +int min10(int a, int b) +{ + if (b >= a) + return a > b ? b : a; + return 0; +} + +int min11(int a, int b) +{ + if (b > a) + return a < b ? a : b; + return 0; +} + +int min12(int a, int b) +{ + if (b > a) + return a > b ? b : a; + return 0; +} + +int min13(int a, int b) +{ + if (b >= a) + return a <= b ? a : b; + return 0; +} + +int min14(int a, int b) +{ + if (b >= a) + return a >= b ? b : a; + return 0; +} + +int min15(int a, int b) +{ + if (b > a) + return a <= b ? a : b; + return 0; +} + +int min16(int a, int b) +{ + if (b > a) + return a >= b ? b : a; + return 0; +} + +/* { dg-final { scan-tree-dump-not "MIN_EXPR" "dom2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c new file mode 100644 index 00000000000..732126d7449 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c @@ -0,0 +1,117 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + +int max1(int a, int b) +{ + if (a <= b) + return a < b ? b : a; + return 0; +} + +int max2(int a, int b) +{ + if (a <= b) + return a > b ? a : b; + return 0; +} + +int max3(int a, int b) +{ + if (a < b) + return a < b ? b : a; + return 0; +} + +int max4(int a, int b) +{ + if (a < b) + return a > b ? a : b; + return 0; +} + +int max5(int a, int b) +{ + if (a <= b) + return a <= b ? b : a; + return 0; +} + +int max6(int a, int b) +{ + if (a <= b) + return a >= b ? a : b; + return 0; +} + +int max7(int a, int b) +{ + if (a < b) + return a <= b ? b : a; + return 0; +} + +int max8(int a, int b) +{ + if (b > a) + return a >= b ? a : b; + return 0; +} + +int max9(int a, int b) +{ + if (b >= a) + return a < b ? b : a; + return 0; +} + +int max10(int a, int b) +{ + if (b >= a) + return a > b ? a : b; + return 0; +} + +int max11(int a, int b) +{ + if (b > a) + return a < b ? b : a; + return 0; +} + +int max12(int a, int b) +{ + if (b > a) + return a > b ? a : b; + return 0; +} + +int max13(int a, int b) +{ + if (b >= a) + return a <= b ? b : a; + return 0; +} + +int max14(int a, int b) +{ + if (b >= a) + return a >= b ? a : b; + return 0; +} + +int max15(int a, int b) +{ + if (b > a) + return a <= b ? b : a; + return 0; +} + +int max16(int a, int b) +{ + if (b > a) + return a >= b ? a : b; + return 0; +} + +/* { dg-final { scan-tree-dump-not "MAX_EXPR" "dom2" } } */ + diff --git a/gcc/tree-ssa-scopedtables.cc b/gcc/tree-ssa-scopedtables.cc index e53dfd445ea..c367d37fa9b 100644 --- a/gcc/tree-ssa-scopedtables.cc +++ b/gcc/tree-ssa-scopedtables.cc @@ -127,10 +127,49 @@ avail_exprs_stack::simplify_binary_operation (gimple *stmt, switch (code) { - /* For these cases, if we know the operands - are equal, then we know the result. */ + /* For these cases, if we know some relationships + between the operands, then we can simplify. */ case MIN_EXPR: case MAX_EXPR: + { + /* Build a simple equality expr and query the hash table + for it. */ + struct hashable_expr expr; + expr.type = boolean_type_node; + expr.kind = EXPR_BINARY; + expr.ops.binary.op = LE_EXPR; + tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); + if (tree_swap_operands_p (rhs1, rhs2)) + std::swap (rhs1, rhs2); + expr.ops.binary.opnd0 = rhs1; + expr.ops.binary.opnd1 = rhs2; + class expr_hash_elt element2 (&expr, NULL_TREE); + expr_hash_elt **slot + = m_avail_exprs->find_slot (&element2, NO_INSERT); + + /* If the query was successful and returned a nonzero + result, then we know the result of the MIN/MAX, even + though it is not a constant value. */ + if (slot && *slot && integer_onep ((*slot)->lhs ())) + return code == MIN_EXPR ? rhs1 : rhs2; + + /* Try again, this time with GE_EXPR. */ + expr.ops.binary.op = GE_EXPR; + class expr_hash_elt element3 (&expr, NULL_TREE); + slot = m_avail_exprs->find_slot (&element3, NO_INSERT); + + /* If the query was successful and returned a nonzero + result, then we know the result of the MIN/MAX, even + though it is not a constant value. */ + if (slot && *slot && integer_onep ((*slot)->lhs ())) + return code == MIN_EXPR ? rhs2 : rhs1; + + break; + } + + /* For these cases, if we know the operands + are equal, then we know the result. */ case BIT_IOR_EXPR: case BIT_AND_EXPR: case BIT_XOR_EXPR: @@ -151,8 +190,12 @@ avail_exprs_stack::simplify_binary_operation (gimple *stmt, expr.type = boolean_type_node; expr.kind = EXPR_BINARY; expr.ops.binary.op = EQ_EXPR; - expr.ops.binary.opnd0 = gimple_assign_rhs1 (stmt); - expr.ops.binary.opnd1 = gimple_assign_rhs2 (stmt); + tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); + if (tree_swap_operands_p (rhs1, rhs2)) + std::swap (rhs1, rhs2); + expr.ops.binary.opnd0 = rhs1; + expr.ops.binary.opnd1 = rhs2; class expr_hash_elt element2 (&expr, NULL_TREE); expr_hash_elt **slot = m_avail_exprs->find_slot (&element2, NO_INSERT); @@ -168,8 +211,6 @@ avail_exprs_stack::simplify_binary_operation (gimple *stmt, { switch (code) { - case MIN_EXPR: - case MAX_EXPR: case BIT_IOR_EXPR: case BIT_AND_EXPR: return gimple_assign_rhs1 (stmt);