From 65e0e5779aea9e529c436466a995269f97375674 Mon Sep 17 00:00:00 2001 From: Virgile Prevosto <virgile.prevosto@m4x.org> Date: Mon, 2 Mar 2020 17:12:39 +0100 Subject: [PATCH] [constfold] constfold unary - on float also minor refactoring of smart constructor for float constants --- src/kernel_services/ast_queries/cil.ml | 91 +++++++++++-------- tests/syntax/compile_constant.c | 4 + .../syntax/oracle/compile_constant.res.oracle | 2 + 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index 6db513bc25a..d792b7e40ff 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -3051,7 +3051,16 @@ let integer_constant i = CInt64(Integer.of_int i, IInt, None) (* Construct an integer. Use only for values that fit on 31 bits *) let integer ~loc (i: int) = new_exp ~loc (Const (integer_constant i)) -let kfloat ~loc k f = new_exp ~loc (Const (CReal(f,k,None))) +let kfloat ~loc k f = + let is_single_precision = + match k with FFloat -> true | FDouble | FLongDouble -> false + in + let f = + if is_single_precision then + Floating_point.round_to_single_precision_float f + else f + in + new_exp ~loc (Const (CReal(f,k,None))) let zero ~loc = integer ~loc 0 let one ~loc = integer ~loc 1 @@ -4407,29 +4416,43 @@ and constFold (machdep: bool) (e: exp) : exp = let loc = e.eloc in match e.enode with BinOp(bop, e1, e2, tres) -> constFoldBinOp ~loc machdep bop e1 e2 tres - | UnOp(unop, e1, tres) -> begin - try - let tk = - match unrollTypeSkel tres with - | TInt(ik, _) -> ik - | TEnum (ei,_) -> ei.ekind - | _ -> raise Not_found (* probably a float *) - in - let e1c = constFold machdep e1 in - match e1c.enode with - Const(CInt64(i,_ik,repr)) -> begin - match unop with - Neg -> - let repr = Extlib.opt_map (fun s -> "-" ^ s) repr in - kinteger64 ~loc ?repr ~kind:tk (Integer.neg i) - | BNot -> kinteger64 ~loc ~kind:tk (Integer.lognot i) - | LNot -> - if Integer.equal i Integer.zero then one ~loc - else zero ~loc - end - | _ -> if e1 == e1c then e else new_exp ~loc (UnOp(unop, e1c, tres)) - with Not_found -> e + | UnOp(unop, e1, tres) when isIntegralType tres -> begin + let tk = + match unrollTypeSkel tres with + | TInt(ik, _) -> ik + | TEnum (ei,_) -> ei.ekind + | _ -> assert false (* tres is an integral type *) + in + let e1c = constFold machdep e1 in + match e1c.enode with + Const(CInt64(i,_ik,repr)) -> begin + match unop with + Neg -> + let repr = Extlib.opt_map (fun s -> "-" ^ s) repr in + kinteger64 ~loc ?repr ~kind:tk (Integer.neg i) + | BNot -> kinteger64 ~loc ~kind:tk (Integer.lognot i) + | LNot -> + if Integer.equal i Integer.zero then one ~loc + else zero ~loc + end + | _ -> if e1 == e1c then e else new_exp ~loc (UnOp(unop, e1c, tres)) end + | UnOp(unop, e1, tres) when isArithmeticType tres -> begin + let tk = + match unrollTypeSkel tres with + | TFloat(fk,_) -> fk + | _ -> assert false (*tres is arithmetic but not integral, i.e. Float *) + in + let e1c = constFold machdep e1 in + match e1c.enode with + | Const (CReal(f,_,_)) -> begin + match unop with + | Neg -> kfloat ~loc tk (-. f) + | _ -> if e1 == e1c then e else new_exp ~loc (UnOp(unop,e1c,tres)) + end + | _ -> if e1 == e1c then e else new_exp ~loc (UnOp(unop,e1c,tres)) + end + | UnOp _ -> e (* Characters are integers *) | Const(CChr c) -> new_exp ~loc (Const(charConstToIntConstant c)) | Const(CEnum {eival = v}) -> constFold machdep v @@ -4706,28 +4729,16 @@ and constFoldBinOp ~loc (machdep: bool) bop e1 e2 tres = | TFloat(fk,_) -> fk | _ -> Kernel.fatal "constFoldBinOp: not a floating type" in - let is_single_precision = - match tk with - | FFloat -> true - | FDouble | FLongDouble -> false - in - let mkFloat f = - let f = - if is_single_precision then - Floating_point.round_to_single_precision_float f - else f - in - new_exp ~loc (Const (CReal(f,tk,None))) - in match bop, e1'.enode, e2'.enode with | PlusA, Const(CReal(f1,fk1,_)), Const(CReal(f2,fk2,_)) when fk1 = fk2 -> - mkFloat (f1 +. f2) + kfloat ~loc tk (f1 +. f2) | MinusA, Const(CReal(f1,fk1,_)), Const(CReal(f2,fk2,_)) when fk1 = fk2 -> - mkFloat (f1 -. f2) + kfloat ~loc tk (f1 -. f2) | Mult, Const(CReal(f1,fk1,_)), Const(CReal(f2,fk2,_)) when fk1 = fk2 -> - mkFloat (f1 *. f2) + kfloat ~loc tk (f1 *. f2) | Div, Const(CReal(f1,fk1,_)), Const(CReal(f2,fk2,_)) when fk1 = fk2 -> - mkFloat (f1 /. f2) (*might be infinity or NaN, but that's still a float*) + (*might be infinity or NaN, but that's still a float*) + kfloat ~loc tk (f1 /. f2) | _ -> new_exp ~loc (BinOp(bop,e1',e2',tres)) end else new_exp ~loc (BinOp(bop, e1', e2', tres)) diff --git a/tests/syntax/compile_constant.c b/tests/syntax/compile_constant.c index dc2acdcdd52..2570c1a0849 100644 --- a/tests/syntax/compile_constant.c +++ b/tests/syntax/compile_constant.c @@ -1,2 +1,6 @@ #define M0(x) (x)*(x)<4.0?0.0:1.0 char pixels[] = {M0(0.0), M0(1), M0(2.0f)}; + +char test_neg = { (-0.) ? 1. : 2. }; + +char test_ge = { ((-1.) >= 0.) ? 1. : 2. }; diff --git a/tests/syntax/oracle/compile_constant.res.oracle b/tests/syntax/oracle/compile_constant.res.oracle index d5b6a340f31..f0dc821e08e 100644 --- a/tests/syntax/oracle/compile_constant.res.oracle +++ b/tests/syntax/oracle/compile_constant.res.oracle @@ -1,4 +1,6 @@ [kernel] Parsing tests/syntax/compile_constant.c (with preprocessing) /* Generated by Frama-C */ char pixels[3] = {(char)0.0, (char)0.0, (char)1.0}; +char test_neg = (char)2.; +char test_ge = (char)2.; -- GitLab