blob: 0c9c5b5c62deb0a6a36fdacfc417913958a2e3e5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
(* *********************************************************************)
(* *)
(* The Compcert verified compiler *)
(* *)
(* Xavier Leroy, Collège de France and Inria Paris *)
(* *)
(* Copyright Institut National de Recherche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU General Public License as published by *)
(* the Free Software Foundation, either version 2 of the License, or *)
(* (at your option) any later version. This file is also distributed *)
(* under the terms of the INRIA Non-Commercial License Agreement. *)
(* *)
(* *********************************************************************)
Require Import Coqlib Maps Errors.
Require Import AST Events Cminor.
Require Import Cminortyping.
Definition tyenv := ident -> typ.
Definition known_idents := PTree.t unit.
Definition is_known (ki: known_idents) (id: ident) :=
match ki!id with Some _ => true | None => false end.
Definition safe_unop (op: unary_operation) : bool :=
match op with
| Ointoffloat | Ointuoffloat | Ofloatofint | Ofloatofintu => false
| Ointofsingle | Ointuofsingle | Osingleofint | Osingleofintu => false
| Olongoffloat | Olonguoffloat | Ofloatoflong | Ofloatoflongu => false
| Olongofsingle | Olonguofsingle | Osingleoflong | Osingleoflongu => false
| _ => true
end.
Definition safe_binop (op: binary_operation) : bool :=
match op with
| Odiv | Odivu | Omod | Omodu => false
| Odivl | Odivlu | Omodl | Omodlu => false
| Ocmpl _ | Ocmplu _ => false
| _ => true
end.
Fixpoint safe_expr (ki: known_idents) (a: expr) : bool :=
match a with
| Evar v => is_known ki v
| Econst c => true
| Eunop op e1 => safe_unop op && safe_expr ki e1
| Ebinop op e1 e2 => safe_binop op && safe_expr ki e1 && safe_expr ki e2
| Eload chunk e => false
end.
Definition Sselection (id: ident) (ty: typ) (cond ifso ifnot: expr) : stmt :=
Sbuiltin (Some id) (EF_select ty) (cond :: ifso :: ifnot :: nil).
Inductive stmt_class : Type :=
| SCskip
| SCassign (id: ident) (a: expr)
| SCother.
Function classify_stmt (s: stmt) : stmt_class :=
match s with
| Sskip => SCskip
| Sassign id a => SCassign id a
| Sseq Sskip s => classify_stmt s
| Sseq s Sskip => classify_stmt s
| _ => SCother
end.
Definition if_conversion_base
(ki: known_idents) (env: tyenv)
(cond: expr) (id: ident) (ifso ifnot: expr) : option stmt :=
if is_known ki id && safe_expr ki ifso && safe_expr ki ifnot
then Some (Sselection id (env id) cond ifso ifnot)
else None.
Definition if_conversion
(ki: known_idents) (env: tyenv)
(cond: expr) (ifso ifnot: stmt) : option stmt :=
match classify_stmt ifso, classify_stmt ifnot with
| SCskip, SCassign id a =>
if_conversion_base ki env cond id (Evar id) a
| SCassign id a, SCskip =>
if_conversion_base ki env cond id a (Evar id)
| SCassign id1 a1, SCassign id2 a2 =>
if ident_eq id1 id2 then if_conversion_base ki env cond id1 a1 a2 else None
| _, _ => None
end.
Fixpoint transf_stmt (ki: known_idents) (env: tyenv) (s: stmt) : stmt :=
match s with
| Sskip => s
| Sassign _ _ => s
| Sstore _ _ _ => s
| Scall _ _ _ _ => s
| Stailcall _ _ _ => s
| Sbuiltin _ _ _ => s
| Sseq s1 s2 => Sseq (transf_stmt ki env s1) (transf_stmt ki env s2)
| Sifthenelse e s1 s2 =>
match if_conversion ki env e s1 s2 with
| Some s => s
| None => Sifthenelse e (transf_stmt ki env s1) (transf_stmt ki env s2)
end
| Sloop s1 => Sloop (transf_stmt ki env s1)
| Sblock s1 => Sblock (transf_stmt ki env s1)
| Sexit _ => s
| Sswitch _ _ _ _ => s
| Sreturn _ => s
| Slabel lbl s1 => Slabel lbl (transf_stmt ki env s1)
| Sgoto _ => s
end.
Definition known_id (f: function) : known_idents :=
let add (ki: known_idents) (id: ident) := PTree.set id tt ki in
List.fold_left add f.(fn_vars)
(List.fold_left add f.(fn_params) (PTree.empty unit)).
Local Open Scope error_monad_scope.
Definition transf_function (f: function) : res function :=
let ki := known_id f in
do env <- type_function f;
OK (mkfunction f.(fn_sig) f.(fn_params) f.(fn_vars) f.(fn_stackspace)
(transf_stmt ki env f.(fn_body))).
Definition transf_fundef (fd: fundef) : res fundef :=
transf_partial_fundef transf_function fd.
Definition transf_program (p: program) : res program :=
transform_partial_program transf_fundef p.
|