[PATCH] ada: Evaluate argument of optimized operators
Samuel Tardieu
sam@rfc1149.net
Thu Aug 7 12:40:00 GMT 2008
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.
The accompanying test program must execute without raising an exception.
Tested on i686-pc-linux-gnu. Ok for trunk?
gcc/ada/
* exp_ch4.adb (Expand_N_Op_Expon): Force evaluation of
left argument even when right argument is 0.
(Expand_N_Op_Mod): Ditto when right argument is 1.
(Expand_N_Op_Multiply): Ditto when any argument is 0.
(Expand_N_Op_Rem): Ditto when right argument is 1.
gcc/testsuite/
* gnat.dg/exp0_eval.adb: New.
---
gcc/ada/exp_ch4.adb | 20 +++++++++++++++-----
gcc/testsuite/gnat.dg/exp0_eval.adb | 31 +++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/gnat.dg/exp0_eval.adb
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index d0b60f3..0a1cd26 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -5466,6 +5466,7 @@ package body Exp_Ch4 is
-- X ** 0 = 1 (or 1.0)
if Expv = 0 then
+ Force_Evaluation (Base);
if Ekind (Typ) in Integer_Kind then
Xnode := Make_Integer_Literal (Loc, Intval => 1);
else
@@ -5940,6 +5941,7 @@ package body Exp_Ch4 is
and then Compile_Time_Known_Value (Right)
and then Expr_Value (Right) = Uint_1
then
+ Force_Evaluation (Left);
Rewrite (N, Make_Integer_Literal (Loc, 0));
Analyze_And_Resolve (N, Typ);
return;
@@ -6013,12 +6015,19 @@ package body Exp_Ch4 is
-- N * 0 = 0 * N = 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
+ Force_Evaluation (Lop);
+ Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
+ Analyze_And_Resolve (N, Typ);
+ return;
+ end if;
+
+ if Compile_Time_Known_Value (Lop)
+ and then Expr_Value (Lop) = Uint_0
then
+ Force_Evaluation (Rop);
Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
Analyze_And_Resolve (N, Typ);
return;
@@ -6497,6 +6506,7 @@ package body Exp_Ch4 is
and then Compile_Time_Known_Value (Right)
and then Expr_Value (Right) = Uint_1
then
+ Force_Evaluation (Left);
Rewrite (N, Make_Integer_Literal (Loc, 0));
Analyze_And_Resolve (N, Typ);
return;
diff --git a/gcc/testsuite/gnat.dg/exp0_eval.adb b/gcc/testsuite/gnat.dg/exp0_eval.adb
new file mode 100644
index 0000000..11edd7d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/exp0_eval.adb
@@ -0,0 +1,31 @@
+-- { dg-do run }
+with Interfaces; use Interfaces;
+procedure Exp0_Eval is
+
+ F_Count : Natural := 0;
+
+ function F return Integer is
+ begin
+ F_Count := F_Count + 1;
+ return 1;
+ end F;
+
+ function F return Unsigned_32 is
+ begin
+ F_Count := F_Count + 1;
+ return 1;
+ end F;
+
+ R : constant Integer :=
+ F ** 0 +
+ F * 0 +
+ 0 * F +
+ Integer (Unsigned_32'(F) mod 1) +
+ Integer (Unsigned_32'(F) rem 1);
+ pragma Warnings (Off, R);
+begin
+ if F_Count /= 5 then
+ raise Program_Error
+ with "incorrect numbers of calls to F:" & F_Count'Img;
+ end if;
+end Exp0_Eval;
--
1.6.0.rc0.182.gb96c7
More information about the Gcc-patches
mailing list