? misc/1CG.m3 Index: misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.11 diff -u -r1.11 CG.i3 --- misc/CG.i3 4 Feb 2010 02:11:30 -0000 1.11 +++ misc/CG.i3 14 Mar 2010 12:36:28 -0000 @@ -8,7 +8,7 @@ INTERFACE CG; -IMPORT Target, M3CG, M3; +IMPORT Target, M3CG, M3, TInt; (* This interface provides a single front-end specific veneer over @@ -405,7 +405,11 @@ (*------------------------------------------------------------ load/store ---*) -PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); +PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; + min_valid: BOOLEAN := FALSE; + max_valid: BOOLEAN := FALSE; + min: Target.Int := TInt.Zero; + max: Target.Int := TInt.Zero); (* push ; s0.t := Mem [ ADR(v) + o : s ] *) PROCEDURE Load_addr_of (v: Var; o: Offset; a: Alignment); @@ -417,8 +421,12 @@ PROCEDURE Load_indirect (t: Type; o: Offset; s: Size); (* s0.t := Mem [s0.A + o : s] *) -PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); -(* == Load (v, o, t.size, t.align, t) *) +PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; + min_valid: BOOLEAN := FALSE; + max_valid: BOOLEAN := FALSE; + min: Target.Int := TInt.Zero; + max: Target.Int := TInt.Zero); +(* == Load (v, o, t.size, t.align, t, min/max...) *) PROCEDURE Load_addr (v: Var; o: Offset := 0); (* == Load (v, o, Target.Address.size, Target.Address.align, Type.Addr) *) Index: misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.36 diff -u -r1.36 CG.m3 --- misc/CG.m3 18 Feb 2010 02:33:12 -0000 1.36 +++ misc/CG.m3 14 Mar 2010 12:36:28 -0000 @@ -43,6 +43,10 @@ next : Val; (* link for lists *) int : Target.Int; (* literal integer value *) float : Target.Float; (* literal floating point value *) + min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) + max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) + min : Target.Int := TInt.Zero; (* the minimum possible value *) + max : Target.Int := TInt.Zero; (* the maximum possible value *) END; TYPE @@ -613,6 +617,11 @@ v.bits := NIL; END; + v.min := TInt.Zero; + v.max := TInt.Zero; + v.min_valid := FALSE; + v.max_valid := FALSE; + RETURN v; END Pop; @@ -775,6 +784,10 @@ x.temp_bits := FALSE; x.base := NIL; x.bits := NIL; + x.min := TInt.Zero; + x.max := TInt.Zero; + x.min_valid := FALSE; + x.max_valid := FALSE; END Release_temps; PROCEDURE Force1 (tag: TEXT) = @@ -1274,7 +1287,11 @@ (*------------------------------------------------------------ load/store ---*) -PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = +PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; + min_valid: BOOLEAN := FALSE; + max_valid: BOOLEAN := FALSE; + min: Target.Int := TInt.Zero; + max: Target.Int := TInt.Zero) = VAR size := TargetMap.CG_Size [t]; align := TargetMap.CG_Align [t]; @@ -1284,7 +1301,7 @@ BEGIN IF (size = s) AND ((a+o) MOD align) = 0 THEN (* a simple aligned load *) - SimpleLoad (v, o, t); + SimpleLoad (v, o, t, min_valid, max_valid, min, max); ELSIF (size < s) THEN Err ("load size too large"); @@ -1299,7 +1316,7 @@ align := (a+o) MOD best_align; IF (s = best_size) AND (align = 0) THEN (* this is a simple partial word load *) - SimpleLoad (v, o, best_type); + SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); ELSE (* unaligned, partial load *) cg.load (v, AsBytes (o - align), best_type, StackType[t]); @@ -1320,7 +1337,11 @@ END; END Load; -PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = +PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; + min_valid: BOOLEAN := FALSE; + max_valid: BOOLEAN := FALSE; + min: Target.Int := TInt.Zero; + max: Target.Int := TInt.Zero) = BEGIN WITH x = stack [SCheck (0, "SimpleLoad")] DO x.kind := VKind.Direct; @@ -1332,6 +1353,10 @@ x.bits := NIL; x.offset := o; x.next := NIL; + x.min_valid := min_valid; + x.max_valid := max_valid; + x.min := min; + x.max := max; END; INC (tos); END SimpleLoad; @@ -1348,6 +1373,10 @@ x.bits := NIL; x.offset := o; x.next := NIL; + x.min := TInt.Zero; + x.max := TInt.Zero; + x.min_valid := FALSE; + x.max_valid := FALSE; END; INC (tos); END Load_addr_of; @@ -1356,11 +1385,19 @@ BEGIN Load_addr_of (v, o, a); stack[tos-1].temp_base := TRUE; + stack[tos-1].min := TInt.Zero; + stack[tos-1].max := TInt.Zero; + stack[tos-1].min_valid := FALSE; + stack[tos-1].max_valid := FALSE; END Load_addr_of_temp; -PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = +PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; + min_valid: BOOLEAN := FALSE; + max_valid: BOOLEAN := FALSE; + min: Target.Int := TInt.Zero; + max: Target.Int := TInt.Zero) = BEGIN - SimpleLoad (v, o, t); + SimpleLoad (v, o, t, min_valid, max_valid, min, max); END Load_int; PROCEDURE Load_addr (v: Var; o: Offset) = @@ -1824,6 +1861,10 @@ WITH x = stack[tos-1] DO x.kind := VKind.Integer; x.int := i; + x.min_valid := TRUE; + x.max_valid := TRUE; + x.min := i; + x.max := i; END; END Load_integer; @@ -1840,12 +1881,134 @@ (*------------------------------------------------------------ arithmetic ---*) PROCEDURE Compare (t: ZType; op: Cmp) = - BEGIN - IF Force_pair (commute := TRUE) THEN - op := M3CG.SwappedCompare [op]; + VAR always_true: BOOLEAN; + always_false: BOOLEAN; + left_type: Type; + right_type: Type; + left_min: Target.Int; + left_max: Target.Int; + right_min: Target.Int; + right_max: Target.Int; + left_signed: BOOLEAN; + right_signed: BOOLEAN; + BEGIN + + always_true := FALSE; + always_false := FALSE; + + WITH left = stack [SCheck (2, "Compare-left")], + right = stack [SCheck (1, "Compare-right")] DO + + left_type := left.type; + right_type := right.type; + + IF left.min_valid + AND left.max_valid + AND right.min_valid + AND right.max_valid + AND Target.OrdinalType[left_type] + AND Target.OrdinalType[right_type] THEN + + left_min := left.min; + left_max := left.max; + right_min := right.min; + right_max := right.max; + left_signed := Target.SignedType[left_type]; + right_signed := Target.SignedType[right_type]; + + (* First handle types that match in signedness. *) + + IF left_signed = right_signed THEN + + (* Check for ranges with no overlap. *) + + IF left_signed (* and right_signed *) THEN + IF TInt.LT(left_max, right_min) THEN + always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; + ELSIF TInt.GT(left_min, right_max) THEN + always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; + END; + ELSE (* left_signed and right_signed both false *) + IF TWord.LT(left_max, right_min) THEN + always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; + ELSIF TWord.GT(left_min, right_max) THEN + always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; + END; + END; + + (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) + + IF NOT (always_true OR always_false) THEN + IF TInt.EQ(left_max, right_min) THEN + always_true := op = Cmp.LE; + always_false := op = Cmp.GT; + ELSIF TInt.EQ(left_min, right_max) THEN + always_true := op = Cmp.GE; + always_false := op = Cmp.LT; + END; + END; + + (* Handle equal subranges with one element, not likely to occur. *) + + IF NOT (always_true OR always_false) THEN + IF TInt.EQ(left_max, left_min) + AND TInt.EQ(left_max, right_max) + AND TInt.EQ(left_max, right_min) THEN + always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; + always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; + END; + END; + ELSE + + (* Now deal with mixed up types (signed compared to unsigned). + * We may be able to merge these by setting some min/max + * to zero. That is, the minimum of an unsigned type is zero. + * However we want to be sure not to interpret unsigned min/max + * as signed. + *) + + IF left_signed THEN + IF TInt.LT(left_max, TInt.Zero) THEN + always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; + ELSIF TInt.EQ(left_max, TInt.Zero) THEN + always_true := op = Cmp.LE; + always_false := op = Cmp.GT; + END; + ELSE (* right is signed *) + IF TInt.LT(right_max, TInt.Zero) THEN + always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; + always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; + ELSIF TInt.EQ(right_max, TInt.Zero) THEN + always_true := op = Cmp.GE; + always_false := op = Cmp.LT; + END; + END; + END; + END; + + <* ASSERT NOT (always_true AND always_false) *> + + IF always_true OR always_false THEN + Discard(right_type); + Discard(left_type); + IF always_true THEN + cg.load_integer (Target.Integer.cg_type, TInt.One); + ELSE + cg.load_integer (Target.Integer.cg_type, TInt.Zero); + END + ELSE + IF Force_pair (commute := TRUE) THEN + op := M3CG.SwappedCompare [op]; + END; + cg.compare (t, Target.Integer.cg_type, op); + SPop (2, "Compare"); + END; END; - cg.compare (t, Target.Integer.cg_type, op); - SPop (2, "Compare"); SPush (Type.Int32); END Compare; @@ -2891,6 +3054,10 @@ x.int := TInt.Zero; x.float := TFloat.ZeroR; x.next := NIL; + x.min := TInt.Zero; + x.max := TInt.Zero; + x.min_valid := FALSE; + x.max_valid := FALSE; END; INC (tos); END SPush; Index: values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -u -r1.13 Variable.m3 --- values/Variable.m3 4 Feb 2010 02:02:57 -0000 1.13 +++ values/Variable.m3 14 Mar 2010 12:36:28 -0000 @@ -360,6 +360,9 @@ END Check; PROCEDURE Load (t: T) = + VAR min: Target.Int; + max: Target.Int; + bounds_valid: BOOLEAN; BEGIN t.used := TRUE; Value.Declare (t); @@ -392,7 +395,10 @@ CG.Boost_alignment (t.align); CG.Load_indirect (t.stk_type, 0, t.size); ELSE - CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); + (*GetBounds (t, min, max); + bounds_valid := TInt.LE(min, max);*) + bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); + CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); END; END; END Load;