From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1914) id ADAC3398B437; Tue, 15 Jun 2021 10:21:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ADAC3398B437 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Pierre-Marie de Rodat To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-1457] [Ada] Add support for folding more and/or expressions X-Act-Checkin: gcc X-Git-Author: Arnaud Charlet X-Git-Refname: refs/heads/master X-Git-Oldrev: 69558e562c0605e1e13d069c3bdbadedf7d72016 X-Git-Newrev: f1e93d3f1ad9091e0c986e6e014738a53f10a50e Message-Id: <20210615102116.ADAC3398B437@sourceware.org> Date: Tue, 15 Jun 2021 10:21:16 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Jun 2021 10:21:16 -0000 https://gcc.gnu.org/g:f1e93d3f1ad9091e0c986e6e014738a53f10a50e commit r12-1457-gf1e93d3f1ad9091e0c986e6e014738a53f10a50e Author: Arnaud Charlet Date: Sat Jan 30 11:52:54 2021 -0500 [Ada] Add support for folding more and/or expressions gcc/ada/ * sem_eval.adb (Eval_Logical_Op, Test_Expression_Is_Foldable): Add support for folding more "and"/"or" expressions. * exp_util.adb (Side_Effect_Free): Fix handling of membership tests. Diff: --- gcc/ada/exp_util.adb | 14 ++++- gcc/ada/sem_eval.adb | 146 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 114 insertions(+), 46 deletions(-) diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 4f2f58d697d..c6c8d6c6253 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -13460,16 +13460,26 @@ package body Exp_Util is -- A binary operator is side effect free if and both operands are -- side effect free. For this purpose binary operators include - -- membership tests and short circuit forms. + -- short circuit forms. when N_Binary_Op - | N_Membership_Test | N_Short_Circuit => return Side_Effect_Free (Left_Opnd (N), Name_Req, Variable_Ref) and then Side_Effect_Free (Right_Opnd (N), Name_Req, Variable_Ref); + -- Membership tests may have either Right_Opnd or Alternatives set + + when N_Membership_Test => + return Side_Effect_Free (Left_Opnd (N), Name_Req, Variable_Ref) + and then + (if Present (Right_Opnd (N)) + then Side_Effect_Free + (Right_Opnd (N), Name_Req, Variable_Ref) + else Side_Effect_Free + (Alternatives (N), Name_Req, Variable_Ref)); + -- An explicit dereference is side effect free only if it is -- a side effect free prefixed reference. diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index a67688d20df..307045a2124 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -2995,10 +2995,12 @@ package body Sem_Eval is -- static if both operands are potentially static (RM 4.9(7), 4.9(20)). procedure Eval_Logical_Op (N : Node_Id) is - Left : constant Node_Id := Left_Opnd (N); - Right : constant Node_Id := Right_Opnd (N); - Stat : Boolean; - Fold : Boolean; + Left : constant Node_Id := Left_Opnd (N); + Right : constant Node_Id := Right_Opnd (N); + Left_Int : Uint := No_Uint; + Right_Int : Uint := No_Uint; + Stat : Boolean; + Fold : Boolean; begin -- If not foldable we are done @@ -3011,64 +3013,88 @@ package body Sem_Eval is -- Compile time evaluation of logical operation - declare - Left_Int : constant Uint := Expr_Value (Left); - Right_Int : constant Uint := Expr_Value (Right); + if Is_Modular_Integer_Type (Etype (N)) then + Left_Int := Expr_Value (Left); + Right_Int := Expr_Value (Right); - begin - if Is_Modular_Integer_Type (Etype (N)) then - declare - Left_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1); - Right_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1); + declare + Left_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1); + Right_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1); - begin - To_Bits (Left_Int, Left_Bits); - To_Bits (Right_Int, Right_Bits); + begin + To_Bits (Left_Int, Left_Bits); + To_Bits (Right_Int, Right_Bits); - -- Note: should really be able to use array ops instead of - -- these loops, but they break the build with a cryptic error - -- during the bind of gnat1 likely due to a wrong computation - -- of a date or checksum. + -- Note: should really be able to use array ops instead of + -- these loops, but they break the build with a cryptic error + -- during the bind of gnat1 likely due to a wrong computation + -- of a date or checksum. - if Nkind (N) = N_Op_And then - for J in Left_Bits'Range loop - Left_Bits (J) := Left_Bits (J) and Right_Bits (J); - end loop; + if Nkind (N) = N_Op_And then + for J in Left_Bits'Range loop + Left_Bits (J) := Left_Bits (J) and Right_Bits (J); + end loop; - elsif Nkind (N) = N_Op_Or then - for J in Left_Bits'Range loop - Left_Bits (J) := Left_Bits (J) or Right_Bits (J); - end loop; + elsif Nkind (N) = N_Op_Or then + for J in Left_Bits'Range loop + Left_Bits (J) := Left_Bits (J) or Right_Bits (J); + end loop; - else - pragma Assert (Nkind (N) = N_Op_Xor); + else + pragma Assert (Nkind (N) = N_Op_Xor); - for J in Left_Bits'Range loop - Left_Bits (J) := Left_Bits (J) xor Right_Bits (J); - end loop; - end if; + for J in Left_Bits'Range loop + Left_Bits (J) := Left_Bits (J) xor Right_Bits (J); + end loop; + end if; - Fold_Uint (N, From_Bits (Left_Bits, Etype (N)), Stat); - end; + Fold_Uint (N, From_Bits (Left_Bits, Etype (N)), Stat); + end; - else - pragma Assert (Is_Boolean_Type (Etype (N))); + else + pragma Assert (Is_Boolean_Type (Etype (N))); - if Nkind (N) = N_Op_And then + if Compile_Time_Known_Value (Left) + and then Compile_Time_Known_Value (Right) + then + Right_Int := Expr_Value (Right); + Left_Int := Expr_Value (Left); + end if; + + if Nkind (N) = N_Op_And then + + -- If Left or Right are not compile time known values it means + -- that the result is always False as per + -- Test_Expression_Is_Foldable. + -- Note that in this case, both Right_Int and Left_Int are set + -- to No_Uint, so need to test for both. + + if Right_Int = No_Uint then + Fold_Uint (N, Uint_0, Stat); + else Fold_Uint (N, Test (Is_True (Left_Int) and then Is_True (Right_Int)), Stat); + end if; + elsif Nkind (N) = N_Op_Or then - elsif Nkind (N) = N_Op_Or then - Fold_Uint (N, - Test (Is_True (Left_Int) or else Is_True (Right_Int)), Stat); + -- If Left or Right are not compile time known values it means + -- that the result is always True. as per + -- Test_Expression_Is_Foldable. + -- Note that in this case, both Right_Int and Left_Int are set + -- to No_Uint, so need to test for both. + if Right_Int = No_Uint then + Fold_Uint (N, Uint_1, Stat); else - pragma Assert (Nkind (N) = N_Op_Xor); Fold_Uint (N, - Test (Is_True (Left_Int) xor Is_True (Right_Int)), Stat); + Test (Is_True (Left_Int) or else Is_True (Right_Int)), Stat); end if; + else + pragma Assert (Nkind (N) = N_Op_Xor); + Fold_Uint (N, + Test (Is_True (Left_Int) xor Is_True (Right_Int)), Stat); end if; - end; + end if; end Eval_Logical_Op; ------------------------ @@ -7193,6 +7219,38 @@ package body Sem_Eval is and then Compile_Time_Known_Value (Op2); end if; + if not Fold + and then not Is_Modular_Integer_Type (Etype (N)) + then + case Nkind (N) is + when N_Op_And => + + -- (False and XXX) = (XXX and False) = False + + Fold := + (Compile_Time_Known_Value (Op1) + and then Is_False (Expr_Value (Op1)) + and then Side_Effect_Free (Op2)) + or else (Compile_Time_Known_Value (Op2) + and then Is_False (Expr_Value (Op2)) + and then Side_Effect_Free (Op1)); + + when N_Op_Or => + + -- (True and XXX) = (XXX and True) = True + + Fold := + (Compile_Time_Known_Value (Op1) + and then Is_True (Expr_Value (Op1)) + and then Side_Effect_Free (Op2)) + or else (Compile_Time_Known_Value (Op2) + and then Is_True (Expr_Value (Op2)) + and then Side_Effect_Free (Op1)); + + when others => null; + end case; + end if; + return; -- Else result is static and foldable. Both operands are static, and