Rust · 5189 bytes Raw Blame History
1 use std::collections::BTreeSet;
2 use std::path::PathBuf;
3
4 use armfortas::driver::OptLevel;
5 use armfortas::testing::{capture_from_path, CaptureRequest, CapturedStage, Stage};
6
7 fn fixture(name: &str) -> PathBuf {
8 let path = PathBuf::from("tests/fixtures").join(name);
9 assert!(path.exists(), "missing test fixture {}", path.display());
10 path
11 }
12
13 fn capture_text(request: CaptureRequest, stage: Stage) -> String {
14 let result = capture_from_path(&request).expect("capture should succeed");
15 match result.get(stage) {
16 Some(CapturedStage::Text(text)) => text.clone(),
17 Some(CapturedStage::Run(_)) => panic!("expected text stage for {}", stage.as_str()),
18 None => panic!("missing requested stage {}", stage.as_str()),
19 }
20 }
21
22 #[test]
23 fn o1_optir_const_folds_integer16_mul() {
24 let raw_ir = capture_text(
25 CaptureRequest {
26 input: fixture("integer16_mul.f90"),
27 requested: BTreeSet::from([Stage::Ir]),
28 opt_level: OptLevel::O0,
29 },
30 Stage::Ir,
31 );
32 let opt_ir = capture_text(
33 CaptureRequest {
34 input: fixture("integer16_mul.f90"),
35 requested: BTreeSet::from([Stage::OptIr]),
36 opt_level: OptLevel::O1,
37 },
38 Stage::OptIr,
39 );
40
41 assert!(
42 raw_ir.contains("imul"),
43 "raw integer(16) IR should still show the wide multiply before O1:\n{}",
44 raw_ir
45 );
46 assert!(
47 opt_ir.contains("const_int 42 : i128") || !opt_ir.contains("i128"),
48 "O1 integer(16) pipeline should fold the wide multiply away before backend, either to a constant or all the way out of the optimized IR:\n{}",
49 opt_ir
50 );
51 assert!(
52 !opt_ir.contains("imul"),
53 "O1 integer(16) pipeline should remove the wide multiply before backend:\n{}",
54 opt_ir
55 );
56 }
57
58 #[test]
59 fn o1_backend_runs_internal_integer16_call() {
60 let result = capture_from_path(&CaptureRequest {
61 input: fixture("integer16_internal_call.f90"),
62 requested: BTreeSet::from([Stage::Run]),
63 opt_level: OptLevel::O1,
64 })
65 .expect("integer(16) internal call should run at O1");
66
67 let run = result
68 .get(Stage::Run)
69 .and_then(CapturedStage::as_run)
70 .expect("missing run capture");
71
72 assert_eq!(
73 run.exit_code, 0,
74 "expected successful O1 integer(16) run:\n{:#?}",
75 run
76 );
77 assert!(
78 run.stdout.contains('1'),
79 "O1 integer(16) internal call program should print score 1:\n{}",
80 run.stdout
81 );
82 }
83
84 #[test]
85 fn o1_integer16_object_snapshot_is_deterministic() {
86 let source = fixture("integer16_mul.f90");
87 let first = capture_text(
88 CaptureRequest {
89 input: source.clone(),
90 requested: BTreeSet::from([Stage::Obj]),
91 opt_level: OptLevel::O1,
92 },
93 Stage::Obj,
94 );
95 let second = capture_text(
96 CaptureRequest {
97 input: source,
98 requested: BTreeSet::from([Stage::Obj]),
99 opt_level: OptLevel::O1,
100 },
101 Stage::Obj,
102 );
103
104 assert_eq!(
105 first, second,
106 "O1 integer(16) object snapshots should stay deterministic once the wide multiply folds away"
107 );
108 }
109
110 #[test]
111 fn o1_optir_promotes_branchy_integer16_local() {
112 let raw_ir = capture_text(
113 CaptureRequest {
114 input: fixture("integer16_branchy_mem2reg.f90"),
115 requested: BTreeSet::from([Stage::Ir]),
116 opt_level: OptLevel::O0,
117 },
118 Stage::Ir,
119 );
120 let opt_ir = capture_text(
121 CaptureRequest {
122 input: fixture("integer16_branchy_mem2reg.f90"),
123 requested: BTreeSet::from([Stage::OptIr]),
124 opt_level: OptLevel::O1,
125 },
126 Stage::OptIr,
127 );
128
129 assert!(
130 raw_ir.contains("alloca"),
131 "raw integer(16) branchy IR should still materialize stack storage before mem2reg:\n{}",
132 raw_ir
133 );
134 assert!(
135 raw_ir.contains("load"),
136 "raw integer(16) branchy IR should still load the local before O1 promotion:\n{}",
137 raw_ir
138 );
139 assert!(
140 !opt_ir.contains("alloca"),
141 "O1 integer(16) pipeline should eliminate the stack slot after mem2reg promotion:\n{}",
142 opt_ir
143 );
144 assert!(
145 !opt_ir.contains("load"),
146 "O1 integer(16) pipeline should eliminate wide loads after promotion:\n{}",
147 opt_ir
148 );
149 }
150
151 #[test]
152 fn o1_branchy_integer16_program_runs_after_mem2reg() {
153 let result = capture_from_path(&CaptureRequest {
154 input: fixture("integer16_branchy_mem2reg.f90"),
155 requested: BTreeSet::from([Stage::Run]),
156 opt_level: OptLevel::O1,
157 })
158 .expect("branchy integer(16) program should run at O1 after mem2reg promotion");
159
160 let run = result
161 .get(Stage::Run)
162 .and_then(CapturedStage::as_run)
163 .expect("missing run capture");
164
165 assert_eq!(
166 run.exit_code, 0,
167 "expected successful O1 branchy integer(16) run:\n{:#?}",
168 run
169 );
170 assert!(
171 run.stdout.contains('1'),
172 "branchy O1 integer(16) program should print score 1:\n{}",
173 run.stdout
174 );
175 }
176