From 2f5da730f159de238500c82b0c6ef6c9ab91b1c2 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 20 Sep 2022 17:14:30 -0400 Subject: [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER to range-ops. * gimple-range-fold.cc (get_letter_range): Move to new class. (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER. * gimple-range-op.cc (class cfn_toupper_tolower): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments. --- gcc/gimple-range-fold.cc | 66 ---------------------------------- gcc/gimple-range-op.cc | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 66 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 417a925ac9f..af1f83f7409 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -887,28 +887,6 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, r.set_varying (type); } -// Return TRUE if we recognize the target character set and return the -// range for lower case and upper case letters. - -static bool -get_letter_range (tree type, irange &lowers, irange &uppers) -{ - // ASCII - int a = lang_hooks.to_target_charset ('a'); - int z = lang_hooks.to_target_charset ('z'); - int A = lang_hooks.to_target_charset ('A'); - int Z = lang_hooks.to_target_charset ('Z'); - - if ((z - a == 25) && (Z - A == 25)) - { - lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z)); - uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z)); - return true; - } - // Unknown character set. - return false; -} - // For a builtin in CALL, return a range in R if known and return // TRUE. Otherwise return FALSE. @@ -944,50 +922,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call, switch (func) { - case CFN_BUILT_IN_TOUPPER: - { - arg = gimple_call_arg (call, 0); - // If the argument isn't compatible with the LHS, do nothing. - if (!range_compatible_p (type, TREE_TYPE (arg))) - return false; - if (!src.get_operand (r, arg)) - return false; - - int_range<3> lowers; - int_range<3> uppers; - if (!get_letter_range (type, lowers, uppers)) - return false; - - // Return the range passed in without any lower case characters, - // but including all the upper case ones. - lowers.invert (); - r.intersect (lowers); - r.union_ (uppers); - return true; - } - - case CFN_BUILT_IN_TOLOWER: - { - arg = gimple_call_arg (call, 0); - // If the argument isn't compatible with the LHS, do nothing. - if (!range_compatible_p (type, TREE_TYPE (arg))) - return false; - if (!src.get_operand (r, arg)) - return false; - - int_range<3> lowers; - int_range<3> uppers; - if (!get_letter_range (type, lowers, uppers)) - return false; - - // Return the range passed in without any upper case characters, - // but including all the lower case ones. - uppers.invert (); - r.intersect (uppers); - r.union_ (lowers); - return true; - } - CASE_CFN_FFS: CASE_CFN_POPCOUNT: // __builtin_ffs* and __builtin_popcount* return [0, prec]. diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index d62dff5f92e..45384d990ae 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -322,6 +322,71 @@ public: } } op_cfn_signbit; +// Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER. +class cfn_toupper_tolower : public range_operator +{ +public: + using range_operator::fold_range; + cfn_toupper_tolower (bool toupper) { m_toupper = toupper; } + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const; +private: + bool get_letter_range (tree type, irange &lowers, irange &uppers) const; + bool m_toupper; +} op_cfn_toupper (true), op_cfn_tolower (false); + +// Return TRUE if we recognize the target character set and return the +// range for lower case and upper case letters. + +bool +cfn_toupper_tolower::get_letter_range (tree type, irange &lowers, + irange &uppers) const +{ + // ASCII + int a = lang_hooks.to_target_charset ('a'); + int z = lang_hooks.to_target_charset ('z'); + int A = lang_hooks.to_target_charset ('A'); + int Z = lang_hooks.to_target_charset ('Z'); + + if ((z - a == 25) && (Z - A == 25)) + { + lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z)); + uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z)); + return true; + } + // Unknown character set. + return false; +} + +bool +cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const +{ + int_range<3> lowers; + int_range<3> uppers; + if (!get_letter_range (type, lowers, uppers)) + return false; + + r = lh; + if (m_toupper) + { + // Return the range passed in without any lower case characters, + // but including all the upper case ones. + lowers.invert (); + r.intersect (lowers); + r.union_ (uppers); + } + else + { + // Return the range passed in without any lower case characters, + // but including all the upper case ones. + uppers.invert (); + r.intersect (uppers); + r.union_ (lowers); + } + return true; +} + // Set up a gimple_range_op_handler for any built in function which can be // supported via range-ops. @@ -358,6 +423,18 @@ gimple_range_op_handler::maybe_builtin_call () m_valid = true; break; + case CFN_BUILT_IN_TOUPPER: + case CFN_BUILT_IN_TOLOWER: + // Only proceed If the argument is compatible with the LHS. + m_op1 = gimple_call_arg (call, 0); + if (range_compatible_p (type, TREE_TYPE (m_op1))) + { + m_valid = true; + m_int = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower + : &op_cfn_toupper; + } + break; + default: break; } -- 2.37.3