On Tue, Nov 7, 2017 at 10:06 PM, Steve Kargl
<s...@troutmask.apl.washington.edu> wrote:
> On Tue, Nov 07, 2017 at 08:26:15PM +0200, Janne Blomqvist wrote:
>> Earlier GFortran used to redefine boolean_type_node, which in the rest
>> of the compiler means the C/C++ _Bool/bool type, to the Fortran
>> default logical type.  When this redefinition was removed, a few
>> issues surfaced. Namely,
>>
>> 1) PR 82869, where we created a boolean tmp variable, and passed it to
>> the runtime library as a Fortran logical variable of a different size.
>>
>> 2) Fortran specifies that logical operations should be done with the
>> default logical kind, not in any other kind.
>>
>> 3) Using 8-bit variables have some issues, such as
>>    - on x86, partial register stalls and length prefix changes.
>>    - s390 has a compare with immediate and jump instruction which
>>      works with 32-bit but not 8-bit quantities.
>>
>> This patch addresses (2) by introducing a type
>> default_logical_type_node which is used when evaluating Fortran
>> logical expressions. (3) is addressed by introducing
>> logical_type_node, a tree representing a logical(kind=4) type which
>> can be used for compiler-generated temporary
>> variables. logical_type_node is always 4 bytes. As a side effect, (1)
>> is also fixed, though there might be some latent bug lurking there
>> still.
>>
>> For x86-64, using the Polyhedron benchmark suite, no performance or
>> code size difference worth mentioning was observed.
>>
>> Regtested on x86_64-pc-linux-gnu. Ok for trunk?
>
> I scanned the patch and it looks ok to me (most a
> mechanical find/replace operation).  One thing those,
>
>> diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
>> index 78477a9..602d369 100644
>> --- a/gcc/fortran/trans-types.c
>> +++ b/gcc/fortran/trans-types.c
>> @@ -62,6 +62,12 @@ tree ppvoid_type_node;
>>  tree pchar_type_node;
>>  tree pfunc_type_node;
>>
>> +tree default_logical_type_node;
>> +tree default_logical_true_node;
>> +tree default_logical_false_node;
>> +tree logical_type_node;
>> +tree logical_true_node;
>> +tree logical_false_node;
>>  tree gfc_charlen_type_node;
>>
>>  tree gfc_float128_type_node = NULL_TREE;
>> @@ -1003,6 +1009,15 @@ gfc_init_types (void)
>>                       wi::mask (n, UNSIGNED,
>>                                 TYPE_PRECISION (size_type_node)));
>>
>> +
>> +  default_logical_type_node = gfc_get_logical_type 
>> (gfc_default_logical_kind);
>> +  default_logical_true_node = build_int_cst (default_logical_type_node, 1);
>> +  default_logical_false_node = build_int_cst (default_logical_type_node, 0);
>> +
>> +  logical_type_node = gfc_get_logical_type (4);
>
> Can you add a comment to note that the 4 is purposely chosen?
> A year or so from now, someone might change this to gfc_default_logical_kind
> without understand/recalling why 4 is used.

The patch contains a comment explaining that in trans-types.h.

However, a bit of further experimenting with my patch revealed that
one can cause these latent bugs I feared to appear by playing with
-fdefault-integer-8 / -finteger-4-integer-8 with the example from
bugzilla (so we end up passing a pointer to a logical(kind=4) variable
but we tell libgfortran it's kind=8). I did fix the most obvious ones
in the attached patch (on top of the previous one), but I'm not
convinced it's exhaustive.

So I wonder, do we actually care enough about -fdefault-integer-8 /
-finteger-4-integer-8 to do this kind of micro-optimization (i.e. use
4 byte logical temporary variables if we can even when we use
-fdefault-integer-8 / -finteger-4-integer-8), or should we play it
safe and just use default_logical_type_node everywhere?




-- 
Janne Blomqvist
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index ed4496c..95faa32 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -5378,7 +5378,8 @@ gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
   tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
                         build_int_cst (type, 1), args[1]);
   tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
-  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
+  tmp = fold_build2_loc (input_location, NE_EXPR, default_logical_type_node,
+                        tmp,
                         build_int_cst (type, 0));
   type = gfc_typenode_for_spec (&expr->ts);
   se->expr = convert (type, tmp);
@@ -5406,7 +5407,7 @@ gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, 
enum tree_code op)
     args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
 
   /* Now, we compare them.  */
-  se->expr = fold_build2_loc (input_location, op, logical_type_node,
+  se->expr = fold_build2_loc (input_location, op, default_logical_type_node,
                              args[0], args[1]);
 }
 
@@ -7464,7 +7465,8 @@ gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
          tmp = gfc_conv_descriptor_data_get (arg1se.expr);
        }
 
-      tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
+      tmp = fold_build2_loc (input_location, NE_EXPR,
+                            default_logical_type_node, tmp,
                             fold_convert (TREE_TYPE (tmp), null_pointer_node));
     }
   se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
@@ -7532,7 +7534,8 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
         }
       gfc_add_block_to_block (&se->pre, &arg1se.pre);
       gfc_add_block_to_block (&se->post, &arg1se.post);
-      tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
+      tmp = fold_build2_loc (input_location, NE_EXPR,
+                            default_logical_type_node, tmp2,
                             fold_convert (TREE_TYPE (tmp2), 
null_pointer_node));
       se->expr = tmp;
     }
@@ -7545,7 +7548,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
       nonzero_charlen = NULL_TREE;
       if (arg1->expr->ts.type == BT_CHARACTER)
        nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
-                                          logical_type_node,
+                                          default_logical_type_node,
                                           arg1->expr->ts.u.cl->backend_decl,
                                           integer_zero_node);
       if (scalar)
@@ -7570,12 +7573,14 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
          gfc_add_block_to_block (&se->post, &arg1se.post);
          gfc_add_block_to_block (&se->pre, &arg2se.pre);
          gfc_add_block_to_block (&se->post, &arg2se.post);
-          tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+          tmp = fold_build2_loc (input_location, EQ_EXPR,
+                                default_logical_type_node,
                                 arg1se.expr, arg2se.expr);
-          tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+          tmp2 = fold_build2_loc (input_location, NE_EXPR,
+                                 default_logical_type_node,
                                  arg1se.expr, null_pointer_node);
           se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                                     logical_type_node, tmp, tmp2);
+                                     default_logical_type_node, tmp, tmp2);
         }
       else
         {
@@ -7593,7 +7598,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
            tmp = gfc_rank_cst[arg1->expr->rank - 1];
          tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
          nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
-                                             logical_type_node, tmp,
+                                             default_logical_type_node, tmp,
                                              build_int_cst (TREE_TYPE (tmp), 
0));
 
           /* A pointer to an array, call library function _gfor_associated.  */
@@ -7607,9 +7612,9 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
           se->expr = build_call_expr_loc (input_location,
                                      gfor_fndecl_associated, 2,
                                      arg1se.expr, arg2se.expr);
-         se->expr = convert (logical_type_node, se->expr);
+         se->expr = convert (default_logical_type_node, se->expr);
          se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                                     logical_type_node, se->expr,
+                                     default_logical_type_node, se->expr,
                                      nonzero_arraylen);
         }
 
@@ -7617,7 +7622,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
         be associated.  */
       if (nonzero_charlen != NULL_TREE)
        se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                                   logical_type_node,
+                                   default_logical_type_node,
                                    se->expr, nonzero_charlen);
     }
 
@@ -7645,14 +7650,16 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
   if (UNLIMITED_POLY (a))
     {
       tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
-      conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+      conda = fold_build2_loc (input_location, NE_EXPR,
+                              default_logical_type_node,
                               tmp, build_int_cst (TREE_TYPE (tmp), 0));
     }
 
   if (UNLIMITED_POLY (b))
     {
       tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
-      condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+      condb = fold_build2_loc (input_location, NE_EXPR,
+                              default_logical_type_node,
                               tmp, build_int_cst (TREE_TYPE (tmp), 0));
     }
 
@@ -7678,16 +7685,16 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
   gfc_conv_expr (&se2, b);
 
   tmp = fold_build2_loc (input_location, EQ_EXPR,
-                        logical_type_node, se1.expr,
+                        default_logical_type_node, se1.expr,
                         fold_convert (TREE_TYPE (se1.expr), se2.expr));
 
   if (conda)
     tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
-                          logical_type_node, conda, tmp);
+                          default_logical_type_node, conda, tmp);
 
   if (condb)
     tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
-                          logical_type_node, condb, tmp);
+                          default_logical_type_node, condb, tmp);
 
   se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
 }
@@ -8052,7 +8059,7 @@ conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
       if (arg->next->expr == NULL)
        /* Only given one arg so generate a null and do a
           not-equal comparison against the first arg.  */
-       se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+       se->expr = fold_build2_loc (input_location, NE_EXPR, 
default_logical_type_node,
                                    arg1se.expr,
                                    fold_convert (TREE_TYPE (arg1se.expr),
                                                  null_pointer_node));
@@ -8068,17 +8075,17 @@ conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
          gfc_add_block_to_block (&se->post, &arg2se.post);
 
          /* Generate test to compare that the two args are equal.  */
-         eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+         eq_expr = fold_build2_loc (input_location, EQ_EXPR, 
default_logical_type_node,
                                     arg1se.expr, arg2se.expr);
          /* Generate test to ensure that the first arg is not null.  */
          not_null_expr = fold_build2_loc (input_location, NE_EXPR,
-                                          logical_type_node,
+                                          default_logical_type_node,
                                           arg1se.expr, null_pointer_node);
 
          /* Finally, the generated test must check that both arg1 is not
             NULL and that it is equal to the second arg.  */
          se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                                     logical_type_node,
+                                     default_logical_type_node,
                                      not_null_expr, eq_expr);
        }
     }
@@ -8308,11 +8315,12 @@ conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * 
expr)
   isnormal = build_call_expr_loc (input_location,
                                  builtin_decl_explicit (BUILT_IN_ISNORMAL),
                                  1, arg);
-  iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
+  iszero = fold_build2_loc (input_location, EQ_EXPR,
+                           default_logical_type_node, arg,
                            build_real_from_int_cst (TREE_TYPE (arg),
                                                     integer_zero_node));
   se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
-                             logical_type_node, isnormal, iszero);
+                             default_logical_type_node, isnormal, iszero);
   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
 }
 
@@ -8337,11 +8345,12 @@ conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr 
* expr)
   signbit = build_call_expr_loc (input_location,
                                 builtin_decl_explicit (BUILT_IN_SIGNBIT),
                                 1, arg);
-  signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+  signbit = fold_build2_loc (input_location, NE_EXPR,
+                            default_logical_type_node,
                             signbit, integer_zero_node);
 
   se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                             logical_type_node, signbit,
+                             default_logical_type_node, signbit,
                              fold_build1_loc (input_location, TRUTH_NOT_EXPR,
                                               TREE_TYPE(isnan), isnan));
 

Reply via email to