[PATCH] ada: Evaluate argument of optimized operators
Robert Dewar
dewar@adacore.com
Sun Aug 10 17:59:00 GMT 2008
Robert Dewar wrote:
> Samuel Tardieu wrote:
>> The optimization of the "**" operator replaces the expression by
>> 1 if the right operand is 0. It means that the left operand is
>> not evaluated in this case. The same thing happens with multiplication
>> by 0 on either side, and with "x mod 1" and "x rem 1".
>>
>> This patch forces the evaluation of the non-zero operand in any case.
>> If the value being evaluated is side-effect-free, "Remove_Side_Effect"
>> called through "Force_Evaluation" will notice it and not generate any
>> code anyway so there is no penalty on doing this.
Actually, on second thoughts, the calls here should be to
Remove_Side_Effects, not to Force_Evaluation. The difference
is that Force_Evaluation freezes variable values, so that
multiple evaluations give the same result, but since we are
certainly not doing multiple evaluations (in fact we intend
to do zero evaluations), it is enough to remove side
effects. Here is the final patch I propose should be applied:
> Index: exp_ch4.adb
> ===================================================================
> --- exp_ch4.adb (revision 134286)
> +++ exp_ch4.adb (working copy)
> @@ -5410,6 +5410,13 @@
> -- X ** 0 = 1 (or 1.0)
>
> if Expv = 0 then
> +
> + -- Call Remove_Side_Effects to ensure that any side effects
> + -- in the ignored left operand (in particular function calls
> + -- to user defined functions) are properly executed.
> +
> + Remove_Side_Effects (Base);
> +
> if Ekind (Typ) in Integer_Kind then
> Xnode := Make_Integer_Literal (Loc, Intval => 1);
> else
> @@ -5884,6 +5891,12 @@
> and then Compile_Time_Known_Value (Right)
> and then Expr_Value (Right) = Uint_1
> then
> + -- Call Remove_Side_Effects to ensure that any side effects in
> + -- the ignored left operand (in particular function calls to
> + -- user defined functions) are properly executed.
> +
> + Remove_Side_Effects (Left);
> +
> Rewrite (N, Make_Integer_Literal (Loc, 0));
> Analyze_And_Resolve (N, Typ);
> return;
> @@ -5932,17 +5945,17 @@
> --------------------------
>
> procedure Expand_N_Op_Multiply (N : Node_Id) is
> - Loc : constant Source_Ptr := Sloc (N);
> - Lop : constant Node_Id := Left_Opnd (N);
> - Rop : constant Node_Id := Right_Opnd (N);
> + Loc : constant Source_Ptr := Sloc (N);
> + Lop : constant Node_Id := Left_Opnd (N);
> + Rop : constant Node_Id := Right_Opnd (N);
>
> - Lp2 : constant Boolean :=
> - Nkind (Lop) = N_Op_Expon
> - and then Is_Power_Of_2_For_Shift (Lop);
> + Lp2 : constant Boolean :=
> + Nkind (Lop) = N_Op_Expon
> + and then Is_Power_Of_2_For_Shift (Lop);
>
> - Rp2 : constant Boolean :=
> - Nkind (Rop) = N_Op_Expon
> - and then Is_Power_Of_2_For_Shift (Rop);
> + Rp2 : constant Boolean :=
> + Nkind (Rop) = N_Op_Expon
> + and then Is_Power_Of_2_For_Shift (Rop);
>
> Ltyp : constant Entity_Id := Etype (Lop);
> Rtyp : constant Entity_Id := Etype (Rop);
> @@ -5955,19 +5968,33 @@
>
> if Is_Integer_Type (Typ) then
>
> - -- N * 0 = 0 * N = 0 for integer types
> + -- N * 0 = 0 for integer types
>
> - if (Compile_Time_Known_Value (Rop)
> - and then Expr_Value (Rop) = Uint_0)
> - or else
> - (Compile_Time_Known_Value (Lop)
> - and then Expr_Value (Lop) = Uint_0)
> + if Compile_Time_Known_Value (Rop)
> + and then Expr_Value (Rop) = Uint_0
> then
> + -- Call Remove_Side_Effects to ensure that any side effects in
> + -- the ignored left operand (in particular function calls to
> + -- user defined functions) are properly executed.
> +
> + Remove_Side_Effects (Lop);
> +
> Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
> Analyze_And_Resolve (N, Typ);
> return;
> end if;
>
> + -- Similar handling for 0 * N = 0
> +
> + if Compile_Time_Known_Value (Lop)
> + and then Expr_Value (Lop) = Uint_0
> + then
> + Remove_Side_Effects (Rop);
> + Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
> + Analyze_And_Resolve (N, Typ);
> + return;
> + end if;
> +
> -- N * 1 = 1 * N = N for integer types
>
> -- This optimisation is not done if we are going to
> @@ -6441,6 +6468,12 @@
> and then Compile_Time_Known_Value (Right)
> and then Expr_Value (Right) = Uint_1
> then
> + -- Call Remove_Side_Effects to ensure that any side effects in the
> + -- ignored left operand (in particular function calls to user defined
>
> + -- functions) are properly executed.
> +
> + Remove_Side_Effects (Left);
> +
> Rewrite (N, Make_Integer_Literal (Loc, 0));
> Analyze_And_Resolve (N, Typ);
> return;
More information about the Gcc-patches
mailing list