new file mode 100644
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+__attribute__((noinline, no_icf))
+_Bool f1(const char *s)
+{
+ unsigned long len = __builtin_strlen (s);
+ _Bool ret = (len == 0);
+ return ret;
+}
+
+/* Check CONVERT_EXPR's get properly handled. */
+__attribute__((noinline, no_icf))
+_Bool f2(const char *s)
+{
+ unsigned len = __builtin_strlen (s);
+ return len == 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-chkp.h"
#include "tree-hash-traits.h"
#include "builtins.h"
+#include "tree-pretty-print.h"
/* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
is an index into strinfo vector, negative value stands for
@@ -2302,6 +2303,43 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi)
else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
handle_pointer_plus (gsi);
}
+ /* strlen (s) eq/ne 0 -> *s eq/ne 0. */
+ else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
+ {
+ tree rhs2 = gimple_assign_rhs2 (stmt);
+ tree_code code = gimple_assign_rhs_code (stmt);
+
+ if ((code == EQ_EXPR || code == NE_EXPR) && integer_zerop (rhs2))
+ {
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (rhs1) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (rhs1);
+ if (is_a<gassign *> (def_stmt)
+ && (gimple_assign_rhs_code (def_stmt) == CONVERT_EXPR
+ || gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
+ && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
+ def_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
+
+ if (gcall *call_stmt = dyn_cast<gcall *> (def_stmt))
+ {
+ tree callee = gimple_call_fndecl (call_stmt);
+ if (valid_builtin_call (call_stmt)
+ && DECL_FUNCTION_CODE (callee) == BUILT_IN_STRLEN)
+ {
+ tree arg = gimple_call_arg (call_stmt, 0);
+ tree op = build2 (MEM_REF, char_type_node, arg, build_zero_cst (TREE_TYPE (arg)));
+ tree temp = make_temp_ssa_name (TREE_TYPE (op), NULL, "strlen");
+ gimple *memref_stmt = gimple_build_assign (temp, op);
+ gimple_stmt_iterator call_gsi = gsi_for_stmt (call_stmt);
+ gsi_insert_before (&call_gsi, memref_stmt, GSI_SAME_STMT);
+ gassign *g = gimple_build_assign (gimple_call_lhs (call_stmt), CONVERT_EXPR, temp);
+ gsi_replace (&call_gsi, g, true);
+ }
+ }
+ }
+ }
+ }
else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
{
tree type = TREE_TYPE (lhs);
@@ -2505,7 +2543,7 @@ const pass_data pass_data_strlen =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0, /* todo_flags_finish */
+ TODO_update_ssa, /* todo_flags_finish */
};
class pass_strlen : public gimple_opt_pass