@c Copyright (C) 2014-2022 Free Software Foundation, Inc. @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @node Match and Simplify @chapter Match and Simplify @cindex Match and Simplify The GIMPLE and GENERIC pattern matching project match-and-simplify tries to address several issues. @enumerate @item unify expression simplifications currently spread and duplicated over separate files like fold-const.cc, gimple-fold.cc and builtins.cc @item allow for a cheap way to implement building and simplifying non-trivial GIMPLE expressions, avoiding the need to go through building and simplifying GENERIC via fold_buildN and then gimplifying via force_gimple_operand @end enumerate To address these the project introduces a simple domain-specific language to write expression simplifications from which code targeting GIMPLE and GENERIC is auto-generated. The GENERIC variant follows the fold_buildN API while for the GIMPLE variant and to address 2) new APIs are introduced. @menu * GIMPLE API:: * The Language:: @end menu @node GIMPLE API @section GIMPLE API @cindex GIMPLE API @deftypefn {GIMPLE function} tree gimple_simplify (enum tree_code, tree, tree, gimple_seq *, tree (*)(tree)) @deftypefnx {GIMPLE function} tree gimple_simplify (enum tree_code, tree, tree, tree, gimple_seq *, tree (*)(tree)) @deftypefnx {GIMPLE function} tree gimple_simplify (enum tree_code, tree, tree, tree, tree, gimple_seq *, tree (*)(tree)) @deftypefnx {GIMPLE function} tree gimple_simplify (enum built_in_function, tree, tree, gimple_seq *, tree (*)(tree)) @deftypefnx {GIMPLE function} tree gimple_simplify (enum built_in_function, tree, tree, tree, gimple_seq *, tree (*)(tree)) @deftypefnx {GIMPLE function} tree gimple_simplify (enum built_in_function, tree, tree, tree, tree, gimple_seq *, tree (*)(tree)) The main GIMPLE API entry to the expression simplifications mimicking that of the GENERIC fold_@{unary,binary,ternary@} functions. @end deftypefn thus providing n-ary overloads for operation or function. The additional arguments are a gimple_seq where built statements are inserted on (if @code{NULL} then simplifications requiring new statements are not performed) and a valueization hook that can be used to tie simplifications to a SSA lattice. In addition to those APIs @code{fold_stmt} is overloaded with a valueization hook: @deftypefn bool fold_stmt (gimple_stmt_iterator *, tree (*)(tree)); @end deftypefn On top of these a @code{fold_buildN}-like API for GIMPLE is introduced: @deftypefn {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum tree_code, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum tree_code, tree, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum tree_code, tree, tree, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum built_in_function, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum built_in_function, tree, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_build (gimple_seq *, location_t, enum built_in_function, tree, tree, tree, tree, tree (*valueize) (tree) = NULL); @deftypefnx {GIMPLE function} tree gimple_convert (gimple_seq *, location_t, tree, tree); @end deftypefn which is supposed to replace @code{force_gimple_operand (fold_buildN (...), ...)} and calls to @code{fold_convert}. Overloads without the @code{location_t} argument exist. Built statements are inserted on the provided sequence and simplification is performed using the optional valueization hook. @node The Language @section The Language @cindex The Language The language in which to write expression simplifications resembles other domain-specific languages GCC uses. Thus it is lispy. Let's start with an example from the match.pd file: @smallexample (simplify (bit_and @@0 integer_all_onesp) @@0) @end smallexample This example contains all required parts of an expression simplification. A simplification is wrapped inside a @code{(simplify ...)} expression. That contains at least two operands - an expression that is matched with the GIMPLE or GENERIC IL and a replacement expression that is returned if the match was successful. Expressions have an operator ID, @code{bit_and} in this case. Expressions can be lower-case tree codes with @code{_expr} stripped off or builtin function code names in all-caps, like @code{BUILT_IN_SQRT}. @code{@@n} denotes a so-called capture. It captures the operand and lets you refer to it in other places of the match-and-simplify. In the above example it is referred to in the replacement expression. Captures are @code{@@} followed by a number or an identifier. @smallexample (simplify (bit_xor @@0 @@0) @{ build_zero_cst (type); @}) @end smallexample In this example @code{@@0} is mentioned twice which constrains the matched expression to have two equal operands. Usually matches are constrained to equal types. If operands may be constants and conversions are involved, matching by value might be preferred in which case use @code{@@@@0} to denote a by-value match and the specific operand you want to refer to in the result part. This example also introduces operands written in C code. These can be used in the expression replacements and are supposed to evaluate to a tree node which has to be a valid GIMPLE operand (so you cannot generate expressions in C code). @smallexample (simplify (trunc_mod integer_zerop@@0 @@1) (if (!integer_zerop (@@1)) @@0)) @end smallexample Here @code{@@0} captures the first operand of the trunc_mod expression which is also predicated with @code{integer_zerop}. Expression operands may be either expressions, predicates or captures. Captures can be unconstrained or capture expressions or predicates. This example introduces an optional operand of simplify, the if-expression. This condition is evaluated after the expression matched in the IL and is required to evaluate to true to enable the replacement expression in the second operand position. The expression operand of the @code{if} is a standard C expression which may contain references to captures. The @code{if} has an optional third operand which may contain the replacement expression that is enabled when the condition evaluates to false. A @code{if} expression can be used to specify a common condition for multiple simplify patterns, avoiding the need to repeat that multiple times: @smallexample (if (!TYPE_SATURATING (type) && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type)) (simplify (minus (plus @@0 @@1) @@0) @@1) (simplify (minus (minus @@0 @@1) @@0) (negate @@1))) @end smallexample Note that @code{if}s in outer position do not have the optional else clause but instead have multiple then clauses. Ifs can be nested. There exists a @code{switch} expression which can be used to chain conditions avoiding nesting @code{if}s too much: @smallexample (simplify (simple_comparison @@0 REAL_CST@@1) (switch /* a CMP (-0) -> a CMP 0 */ (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1))) (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @})) /* x != NaN is always true, other ops are always false. */ (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1)) && ! HONOR_SNANS (@@1)) @{ constant_boolean_node (cmp == NE_EXPR, type); @}))) @end smallexample Is equal to @smallexample (simplify (simple_comparison @@0 REAL_CST@@1) (switch /* a CMP (-0) -> a CMP 0 */ (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@@1))) (cmp @@0 @{ build_real (TREE_TYPE (@@1), dconst0); @}) /* x != NaN is always true, other ops are always false. */ (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@@1)) && ! HONOR_SNANS (@@1)) @{ constant_boolean_node (cmp == NE_EXPR, type); @})))) @end smallexample which has the second @code{if} in the else operand of the first. The @code{switch} expression takes @code{if} expressions as operands (which may not have else clauses) and as a last operand a replacement expression which should be enabled by default if no other condition evaluated to true. Captures can also be used for capturing results of sub-expressions. @smallexample #if GIMPLE (simplify (pointer_plus (addr@@2 @@0) INTEGER_CST_P@@1) (if (is_gimple_min_invariant (@@2))) @{ poly_int64 off; tree base = get_addr_base_and_unit_offset (@@0, &off); off += tree_to_uhwi (@@1); /* Now with that we should be able to simply write (addr (mem_ref (addr @@base) (plus @@off @@1))) */ build1 (ADDR_EXPR, type, build2 (MEM_REF, TREE_TYPE (TREE_TYPE (@@2)), build_fold_addr_expr (base), build_int_cst (ptr_type_node, off))); @}) #endif @end smallexample In the above example, @code{@@2} captures the result of the expression @code{(addr @@0)}. For the outermost expression only its type can be captured, and the keyword @code{type} is reserved for this purpose. The above example also gives a way to conditionalize patterns to only apply to @code{GIMPLE} or @code{GENERIC} by means of using the pre-defined preprocessor macros @code{GIMPLE} and @code{GENERIC} and using preprocessor directives. @smallexample (simplify (bit_and:c integral_op_p@@0 (bit_ior:c (bit_not @@0) @@1)) (bit_and @@1 @@0)) @end smallexample Here we introduce flags on match expressions. The flag used above, @code{c}, denotes that the expression should be also matched commutated. Thus the above match expression is really the following four match expressions: @smallexample (bit_and integral_op_p@@0 (bit_ior (bit_not @@0) @@1)) (bit_and (bit_ior (bit_not @@0) @@1) integral_op_p@@0) (bit_and integral_op_p@@0 (bit_ior @@1 (bit_not @@0))) (bit_and (bit_ior @@1 (bit_not @@0)) integral_op_p@@0) @end smallexample Usual canonicalizations you know from GENERIC expressions are applied before matching, so for example constant operands always come second in commutative expressions. The second supported flag is @code{s} which tells the code generator to fail the pattern if the expression marked with @code{s} does have more than one use and the simplification results in an expression with more than one operator. For example in @smallexample (simplify (pointer_plus (pointer_plus:s @@0 @@1) @@3) (pointer_plus @@0 (plus @@1 @@3))) @end smallexample this avoids the association if @code{(pointer_plus @@0 @@1)} is used outside of the matched expression and thus it would stay live and not trivially removed by dead code elimination. Now consider @code{((x + 3) + -3)} with the temporary holding @code{(x + 3)} used elsewhere. This simplifies down to @code{x} which is desirable and thus flagging with @code{s} does not prevent the transform. Now consider @code{((x + 3) + 1)} which simplifies to @code{(x + 4)}. Despite being flagged with @code{s} the simplification will be performed. The simplification of @code{((x + a) + 1)} to @code{(x + (a + 1))} will not performed in this case though. More features exist to avoid too much repetition. @smallexample (for op (plus pointer_plus minus bit_ior bit_xor) (simplify (op @@0 integer_zerop) @@0)) @end smallexample A @code{for} expression can be used to repeat a pattern for each operator specified, substituting @code{op}. @code{for} can be nested and a @code{for} can have multiple operators to iterate. @smallexample (for opa (plus minus) opb (minus plus) (for opc (plus minus) (simplify... @end smallexample In this example the pattern will be repeated four times with @code{opa, opb, opc} being @code{plus, minus, plus}; @code{plus, minus, minus}; @code{minus, plus, plus}; @code{minus, plus, minus}. To avoid repeating operator lists in @code{for} you can name them via @smallexample (define_operator_list pmm plus minus mult) @end smallexample and use them in @code{for} operator lists where they get expanded. @smallexample (for opa (pmm trunc_div) (simplify... @end smallexample So this example iterates over @code{plus}, @code{minus}, @code{mult} and @code{trunc_div}. Using operator lists can also remove the need to explicitly write a @code{for}. All operator list uses that appear in a @code{simplify} or @code{match} pattern in operator positions will implicitly be added to a new @code{for}. For example @smallexample (define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) (define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL) (simplify (SQRT (POW @@0 @@1)) (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @}))) @end smallexample is the same as @smallexample (for SQRT (BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) POW (BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL) (simplify (SQRT (POW @@0 @@1)) (POW (abs @@0) (mult @@1 @{ built_real (TREE_TYPE (@@1), dconsthalf); @})))) @end smallexample @code{for}s and operator lists can include the special identifier @code{null} that matches nothing and can never be generated. This can be used to pad an operator list so that it has a standard form, even if there isn't a suitable operator for every form. Another building block are @code{with} expressions in the result expression which nest the generated code in a new C block followed by its argument: @smallexample (simplify (convert (mult @@0 @@1)) (with @{ tree utype = unsigned_type_for (type); @} (convert (mult (convert:utype @@0) (convert:utype @@1))))) @end smallexample This allows code nested in the @code{with} to refer to the declared variables. In the above case we use the feature to specify the type of a generated expression with the @code{:type} syntax where @code{type} needs to be an identifier that refers to the desired type. Usually the types of the generated result expressions are determined from the context, but sometimes like in the above case it is required that you specify them explicitly. Another modifier for generated expressions is @code{!} which tells the machinery to only consider the simplification in case the marked expression simplified to a simple operand. Consider for example @smallexample (simplify (plus (vec_cond:s @@0 @@1 @@2) @@3) (vec_cond @@0 (plus! @@1 @@3) (plus! @@2 @@3))) @end smallexample which moves the outer @code{plus} operation to the inner arms of the @code{vec_cond} expression but only if the actual plus operations both simplify. Note that on @code{GENERIC} a simple operand means that the result satisfies @code{!EXPR_P} which can be limiting if the operation itself simplifies but the remaining operand is an (unrelated) expression. As intermediate conversions are often optional there is a way to avoid the need to repeat patterns both with and without such conversions. Namely you can mark a conversion as being optional with a @code{?}: @smallexample (simplify (eq (convert@@0 @@1) (convert@? @@2)) (eq @@1 (convert @@2))) @end smallexample which will match both @code{(eq (convert @@1) (convert @@2))} and @code{(eq (convert @@1) @@2)}. The optional converts are supposed to be all either present or not, thus @code{(eq (convert@? @@1) (convert@? @@2))} will result in two patterns only. If you want to match all four combinations you have access to two additional conditional converts as in @code{(eq (convert1@? @@1) (convert2@? @@2))}. The support for @code{?} marking extends to all unary operations including predicates you declare yourself with @code{match}. Predicates available from the GCC middle-end need to be made available explicitly via @code{define_predicates}: @smallexample (define_predicates integer_onep integer_zerop integer_all_onesp) @end smallexample You can also define predicates using the pattern matching language and the @code{match} form: @smallexample (match negate_expr_p INTEGER_CST (if (TYPE_OVERFLOW_WRAPS (type) || may_negate_without_overflow_p (t)))) (match negate_expr_p (negate @@0)) @end smallexample This shows that for @code{match} expressions there is @code{t} available which captures the outermost expression (something not possible in the @code{simplify} context). As you can see @code{match} has an identifier as first operand which is how you refer to the predicate in patterns. Multiple @code{match} for the same identifier add additional cases where the predicate matches. Predicates can also match an expression in which case you need to provide a template specifying the identifier and where to get its operands from: @smallexample (match (logical_inverted_value @@0) (eq @@0 integer_zerop)) (match (logical_inverted_value @@0) (bit_not truth_valued_p@@0)) @end smallexample You can use the above predicate like @smallexample (simplify (bit_and @@0 (logical_inverted_value @@0)) @{ build_zero_cst (type); @}) @end smallexample Which will match a bitwise and of an operand with its logical inverted value.