xref: /aosp_15_r20/external/toolchain-utils/llvm_tools/patch_utils_unittest.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li#!/usr/bin/env python3
2*760c253cSXin Li# Copyright 2022 The ChromiumOS Authors
3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be
4*760c253cSXin Li# found in the LICENSE file.
5*760c253cSXin Li
6*760c253cSXin Li"""Unit tests for the patch_utils.py file."""
7*760c253cSXin Li
8*760c253cSXin Liimport copy
9*760c253cSXin Liimport io
10*760c253cSXin Liimport json
11*760c253cSXin Lifrom pathlib import Path
12*760c253cSXin Liimport shutil
13*760c253cSXin Liimport subprocess
14*760c253cSXin Liimport tempfile
15*760c253cSXin Liimport unittest
16*760c253cSXin Lifrom unittest import mock
17*760c253cSXin Li
18*760c253cSXin Liimport patch_utils as pu
19*760c253cSXin Li
20*760c253cSXin Li
21*760c253cSXin Liclass TestPatchUtils(unittest.TestCase):
22*760c253cSXin Li    """Test the patch_utils."""
23*760c253cSXin Li
24*760c253cSXin Li    def make_tempdir(self) -> Path:
25*760c253cSXin Li        tmpdir = Path(tempfile.mkdtemp(prefix="patch_utils_unittest"))
26*760c253cSXin Li        self.addCleanup(shutil.rmtree, tmpdir)
27*760c253cSXin Li        return tmpdir
28*760c253cSXin Li
29*760c253cSXin Li    def test_predict_indent(self):
30*760c253cSXin Li        test_str1 = """
31*760c253cSXin Lia
32*760c253cSXin Li  a
33*760c253cSXin Li      a
34*760c253cSXin Li  a
35*760c253cSXin Lia
36*760c253cSXin Li"""
37*760c253cSXin Li        self.assertEqual(pu.predict_indent(test_str1.splitlines()), 2)
38*760c253cSXin Li        test_str2 = """
39*760c253cSXin Lia
40*760c253cSXin Li    a
41*760c253cSXin Li        a
42*760c253cSXin Li    a
43*760c253cSXin Lia
44*760c253cSXin Li"""
45*760c253cSXin Li        self.assertEqual(pu.predict_indent(test_str2.splitlines()), 4)
46*760c253cSXin Li
47*760c253cSXin Li    def test_from_to_dict(self):
48*760c253cSXin Li        """Test to and from dict conversion."""
49*760c253cSXin Li        d = TestPatchUtils._default_json_dict()
50*760c253cSXin Li        d["metadata"] = {
51*760c253cSXin Li            "title": "hello world",
52*760c253cSXin Li            "info": [],
53*760c253cSXin Li            "other_extra_info": {
54*760c253cSXin Li                "extra_flags": [],
55*760c253cSXin Li            },
56*760c253cSXin Li        }
57*760c253cSXin Li        e = pu.PatchEntry.from_dict(TestPatchUtils._mock_dir(), d)
58*760c253cSXin Li        self.assertEqual(d, e.to_dict())
59*760c253cSXin Li
60*760c253cSXin Li        # Test that they aren't serialised the same, as 'd' isn't sorted.
61*760c253cSXin Li        self.assertNotEqual(
62*760c253cSXin Li            json.dumps(d["metadata"]), json.dumps(e.to_dict()["metadata"])
63*760c253cSXin Li        )
64*760c253cSXin Li        self.assertEqual(
65*760c253cSXin Li            ["info", "other_extra_info", "title"],
66*760c253cSXin Li            list(e.to_dict()["metadata"].keys()),
67*760c253cSXin Li        )
68*760c253cSXin Li
69*760c253cSXin Li    def test_patch_path(self):
70*760c253cSXin Li        """Test that we can get the full path from a PatchEntry."""
71*760c253cSXin Li        d = TestPatchUtils._default_json_dict()
72*760c253cSXin Li        with mock.patch.object(Path, "is_dir", return_value=True):
73*760c253cSXin Li            entry = pu.PatchEntry.from_dict(Path("/home/dir"), d)
74*760c253cSXin Li            self.assertEqual(
75*760c253cSXin Li                entry.patch_path(), Path("/home/dir") / d["rel_patch_path"]
76*760c253cSXin Li            )
77*760c253cSXin Li
78*760c253cSXin Li    def test_can_patch_version(self):
79*760c253cSXin Li        """Test that patch application based on version is correct."""
80*760c253cSXin Li        base_dict = TestPatchUtils._default_json_dict()
81*760c253cSXin Li        workdir = TestPatchUtils._mock_dir()
82*760c253cSXin Li        e1 = pu.PatchEntry.from_dict(workdir, base_dict)
83*760c253cSXin Li        self.assertFalse(e1.can_patch_version(3))
84*760c253cSXin Li        self.assertTrue(e1.can_patch_version(4))
85*760c253cSXin Li        self.assertTrue(e1.can_patch_version(5))
86*760c253cSXin Li        self.assertFalse(e1.can_patch_version(9))
87*760c253cSXin Li        base_dict["version_range"] = {"until": 9}
88*760c253cSXin Li        e2 = pu.PatchEntry.from_dict(workdir, base_dict)
89*760c253cSXin Li        self.assertTrue(e2.can_patch_version(0))
90*760c253cSXin Li        self.assertTrue(e2.can_patch_version(5))
91*760c253cSXin Li        self.assertFalse(e2.can_patch_version(9))
92*760c253cSXin Li        base_dict["version_range"] = {"from": 4}
93*760c253cSXin Li        e3 = pu.PatchEntry.from_dict(workdir, base_dict)
94*760c253cSXin Li        self.assertFalse(e3.can_patch_version(3))
95*760c253cSXin Li        self.assertTrue(e3.can_patch_version(5))
96*760c253cSXin Li        self.assertTrue(e3.can_patch_version(1 << 31))
97*760c253cSXin Li        base_dict["version_range"] = {"from": 4, "until": None}
98*760c253cSXin Li        e4 = pu.PatchEntry.from_dict(workdir, base_dict)
99*760c253cSXin Li        self.assertFalse(e4.can_patch_version(3))
100*760c253cSXin Li        self.assertTrue(e4.can_patch_version(5))
101*760c253cSXin Li        self.assertTrue(e4.can_patch_version(1 << 31))
102*760c253cSXin Li        base_dict["version_range"] = {"from": None, "until": 9}
103*760c253cSXin Li        e5 = pu.PatchEntry.from_dict(workdir, base_dict)
104*760c253cSXin Li        self.assertTrue(e5.can_patch_version(0))
105*760c253cSXin Li        self.assertTrue(e5.can_patch_version(5))
106*760c253cSXin Li        self.assertFalse(e5.can_patch_version(9))
107*760c253cSXin Li
108*760c253cSXin Li    def test_can_parse_from_json(self):
109*760c253cSXin Li        """Test that patches be loaded from json."""
110*760c253cSXin Li        patches_json = """
111*760c253cSXin Li[
112*760c253cSXin Li  {
113*760c253cSXin Li    "metadata": {},
114*760c253cSXin Li    "platforms": [],
115*760c253cSXin Li    "rel_patch_path": "cherry/nowhere.patch",
116*760c253cSXin Li    "version_range": {}
117*760c253cSXin Li  },
118*760c253cSXin Li  {
119*760c253cSXin Li    "metadata": {},
120*760c253cSXin Li    "rel_patch_path": "cherry/somewhere.patch",
121*760c253cSXin Li    "version_range": {}
122*760c253cSXin Li  },
123*760c253cSXin Li  {
124*760c253cSXin Li    "rel_patch_path": "where.patch",
125*760c253cSXin Li    "version_range": null
126*760c253cSXin Li  },
127*760c253cSXin Li  {
128*760c253cSXin Li    "rel_patch_path": "cherry/anywhere.patch"
129*760c253cSXin Li  }
130*760c253cSXin Li]
131*760c253cSXin Li    """
132*760c253cSXin Li        result = pu.json_str_to_patch_entries(Path(), patches_json)
133*760c253cSXin Li        self.assertEqual(len(result), 4)
134*760c253cSXin Li
135*760c253cSXin Li        result = pu.json_to_patch_entries(Path(), io.StringIO(patches_json))
136*760c253cSXin Li        self.assertEqual(len(result), 4)
137*760c253cSXin Li
138*760c253cSXin Li    def test_parsed_hunks(self):
139*760c253cSXin Li        """Test that we can parse patch file hunks."""
140*760c253cSXin Li        m = mock.mock_open(read_data=_EXAMPLE_PATCH)
141*760c253cSXin Li
142*760c253cSXin Li        def mocked_open(self, *args, **kwargs):
143*760c253cSXin Li            return m(self, *args, **kwargs)
144*760c253cSXin Li
145*760c253cSXin Li        with mock.patch.object(Path, "open", mocked_open):
146*760c253cSXin Li            e = pu.PatchEntry.from_dict(
147*760c253cSXin Li                TestPatchUtils._mock_dir(), TestPatchUtils._default_json_dict()
148*760c253cSXin Li            )
149*760c253cSXin Li            hunk_dict = e.parsed_hunks()
150*760c253cSXin Li
151*760c253cSXin Li        m.assert_called()
152*760c253cSXin Li        filename1 = "clang/lib/Driver/ToolChains/Clang.cpp"
153*760c253cSXin Li        filename2 = "llvm/lib/Passes/PassBuilder.cpp"
154*760c253cSXin Li        self.assertEqual(set(hunk_dict.keys()), {filename1, filename2})
155*760c253cSXin Li        hunk_list1 = hunk_dict[filename1]
156*760c253cSXin Li        hunk_list2 = hunk_dict[filename2]
157*760c253cSXin Li        self.assertEqual(len(hunk_list1), 1)
158*760c253cSXin Li        self.assertEqual(len(hunk_list2), 2)
159*760c253cSXin Li
160*760c253cSXin Li    def test_apply_when_patch_nonexistent(self):
161*760c253cSXin Li        """Test that we error out when we try to apply a non-existent patch."""
162*760c253cSXin Li        src_dir = TestPatchUtils._mock_dir("somewhere/llvm-project")
163*760c253cSXin Li        patch_dir = TestPatchUtils._mock_dir()
164*760c253cSXin Li        e = pu.PatchEntry.from_dict(
165*760c253cSXin Li            patch_dir, TestPatchUtils._default_json_dict()
166*760c253cSXin Li        )
167*760c253cSXin Li        with mock.patch("subprocess.run", mock.MagicMock()):
168*760c253cSXin Li            self.assertRaises(RuntimeError, lambda: e.apply(src_dir))
169*760c253cSXin Li
170*760c253cSXin Li    def test_apply_success(self):
171*760c253cSXin Li        """Test that we can call apply."""
172*760c253cSXin Li        src_dir = TestPatchUtils._mock_dir("somewhere/llvm-project")
173*760c253cSXin Li        patch_dir = TestPatchUtils._mock_dir()
174*760c253cSXin Li        e = pu.PatchEntry.from_dict(
175*760c253cSXin Li            patch_dir, TestPatchUtils._default_json_dict()
176*760c253cSXin Li        )
177*760c253cSXin Li
178*760c253cSXin Li        # Make a deepcopy of the case for testing commit patch option.
179*760c253cSXin Li        e1 = copy.deepcopy(e)
180*760c253cSXin Li
181*760c253cSXin Li        with mock.patch("pathlib.Path.is_file", return_value=True):
182*760c253cSXin Li            with mock.patch("subprocess.run", mock.MagicMock()):
183*760c253cSXin Li                result = e.apply(src_dir)
184*760c253cSXin Li        self.assertTrue(result.succeeded)
185*760c253cSXin Li
186*760c253cSXin Li        # Test that commit patch option works.
187*760c253cSXin Li        with mock.patch("pathlib.Path.is_file", return_value=True):
188*760c253cSXin Li            with mock.patch("subprocess.run", mock.MagicMock()):
189*760c253cSXin Li                result1 = e1.apply(src_dir, pu.git_am)
190*760c253cSXin Li        self.assertTrue(result1.succeeded)
191*760c253cSXin Li
192*760c253cSXin Li    def test_parse_failed_patch_output(self):
193*760c253cSXin Li        """Test that we can call parse `patch` output."""
194*760c253cSXin Li        fixture = """
195*760c253cSXin Lichecking file a/b/c.cpp
196*760c253cSXin LiHunk #1 SUCCEEDED at 96 with fuzz 1.
197*760c253cSXin LiHunk #12 FAILED at 77.
198*760c253cSXin LiHunk #42 FAILED at 1979.
199*760c253cSXin Lichecking file x/y/z.h
200*760c253cSXin LiHunk #4 FAILED at 30.
201*760c253cSXin Lichecking file works.cpp
202*760c253cSXin LiHunk #1 SUCCEEDED at 96 with fuzz 1.
203*760c253cSXin Li"""
204*760c253cSXin Li        result = pu.parse_failed_patch_output(fixture)
205*760c253cSXin Li        self.assertEqual(result["a/b/c.cpp"], [12, 42])
206*760c253cSXin Li        self.assertEqual(result["x/y/z.h"], [4])
207*760c253cSXin Li        self.assertNotIn("works.cpp", result)
208*760c253cSXin Li
209*760c253cSXin Li    def test_is_git_dirty(self):
210*760c253cSXin Li        """Test if a git directory has uncommitted changes."""
211*760c253cSXin Li        dirpath = self.make_tempdir()
212*760c253cSXin Li
213*760c253cSXin Li        def _run_h(cmd):
214*760c253cSXin Li            subprocess.run(
215*760c253cSXin Li                cmd,
216*760c253cSXin Li                cwd=dirpath,
217*760c253cSXin Li                stdout=subprocess.DEVNULL,
218*760c253cSXin Li                stderr=subprocess.DEVNULL,
219*760c253cSXin Li                check=True,
220*760c253cSXin Li            )
221*760c253cSXin Li
222*760c253cSXin Li        _run_h(["git", "init"])
223*760c253cSXin Li        self.assertFalse(pu.is_git_dirty(dirpath))
224*760c253cSXin Li        test_file = dirpath / "test_file"
225*760c253cSXin Li        test_file.touch()
226*760c253cSXin Li        self.assertTrue(pu.is_git_dirty(dirpath))
227*760c253cSXin Li        _run_h(["git", "add", "."])
228*760c253cSXin Li        _run_h(["git", "commit", "-m", "test"])
229*760c253cSXin Li        self.assertFalse(pu.is_git_dirty(dirpath))
230*760c253cSXin Li        test_file.touch()
231*760c253cSXin Li        self.assertFalse(pu.is_git_dirty(dirpath))
232*760c253cSXin Li        with test_file.open("w", encoding="utf-8"):
233*760c253cSXin Li            test_file.write_text("abc")
234*760c253cSXin Li        self.assertTrue(pu.is_git_dirty(dirpath))
235*760c253cSXin Li
236*760c253cSXin Li    @mock.patch("patch_utils.git_clean_context", mock.MagicMock)
237*760c253cSXin Li    def test_update_version_ranges(self):
238*760c253cSXin Li        """Test the UpdateVersionRanges function."""
239*760c253cSXin Li        dirpath = self.make_tempdir()
240*760c253cSXin Li        patches = [
241*760c253cSXin Li            pu.PatchEntry(
242*760c253cSXin Li                workdir=dirpath,
243*760c253cSXin Li                rel_patch_path="x.patch",
244*760c253cSXin Li                metadata=None,
245*760c253cSXin Li                platforms=None,
246*760c253cSXin Li                version_range={
247*760c253cSXin Li                    "from": 0,
248*760c253cSXin Li                    "until": 2,
249*760c253cSXin Li                },
250*760c253cSXin Li            ),
251*760c253cSXin Li            pu.PatchEntry(
252*760c253cSXin Li                workdir=dirpath,
253*760c253cSXin Li                rel_patch_path="y.patch",
254*760c253cSXin Li                metadata=None,
255*760c253cSXin Li                platforms=None,
256*760c253cSXin Li                version_range={
257*760c253cSXin Li                    "from": 0,
258*760c253cSXin Li                    "until": 2,
259*760c253cSXin Li                },
260*760c253cSXin Li            ),
261*760c253cSXin Li            pu.PatchEntry(
262*760c253cSXin Li                workdir=dirpath,
263*760c253cSXin Li                rel_patch_path="z.patch",
264*760c253cSXin Li                metadata=None,
265*760c253cSXin Li                platforms=None,
266*760c253cSXin Li                version_range={
267*760c253cSXin Li                    "from": 4,
268*760c253cSXin Li                    "until": 5,
269*760c253cSXin Li                },
270*760c253cSXin Li            ),
271*760c253cSXin Li        ]
272*760c253cSXin Li
273*760c253cSXin Li        patches[0].apply = mock.MagicMock(
274*760c253cSXin Li            return_value=pu.PatchResult(
275*760c253cSXin Li                succeeded=False, failed_hunks={"a/b/c": []}
276*760c253cSXin Li            )
277*760c253cSXin Li        )
278*760c253cSXin Li        patches[1].apply = mock.MagicMock(
279*760c253cSXin Li            return_value=pu.PatchResult(succeeded=True)
280*760c253cSXin Li        )
281*760c253cSXin Li        patches[2].apply = mock.MagicMock(
282*760c253cSXin Li            return_value=pu.PatchResult(succeeded=False)
283*760c253cSXin Li        )
284*760c253cSXin Li
285*760c253cSXin Li        # Make a deepcopy of patches to test commit patch option
286*760c253cSXin Li        patches2 = copy.deepcopy(patches)
287*760c253cSXin Li
288*760c253cSXin Li        results, _ = pu.update_version_ranges_with_entries(
289*760c253cSXin Li            1, dirpath, patches, pu.gnu_patch
290*760c253cSXin Li        )
291*760c253cSXin Li
292*760c253cSXin Li        # We should only have updated the version_range of the first patch,
293*760c253cSXin Li        # as that one failed to apply.
294*760c253cSXin Li        self.assertEqual(len(results), 1)
295*760c253cSXin Li        self.assertEqual(results[0].version_range, {"from": 0, "until": 1})
296*760c253cSXin Li        self.assertEqual(patches[0].version_range, {"from": 0, "until": 1})
297*760c253cSXin Li        self.assertEqual(patches[1].version_range, {"from": 0, "until": 2})
298*760c253cSXin Li        self.assertEqual(patches[2].version_range, {"from": 4, "until": 5})
299*760c253cSXin Li
300*760c253cSXin Li        # Test git am option
301*760c253cSXin Li        results2, _ = pu.update_version_ranges_with_entries(
302*760c253cSXin Li            1, dirpath, patches2, pu.git_am
303*760c253cSXin Li        )
304*760c253cSXin Li
305*760c253cSXin Li        # We should only have updated the version_range of the first patch
306*760c253cSXin Li        # via git am, as that one failed to apply.
307*760c253cSXin Li        self.assertEqual(len(results2), 1)
308*760c253cSXin Li        self.assertEqual(results2[0].version_range, {"from": 0, "until": 1})
309*760c253cSXin Li        self.assertEqual(patches2[0].version_range, {"from": 0, "until": 1})
310*760c253cSXin Li        self.assertEqual(patches2[1].version_range, {"from": 0, "until": 2})
311*760c253cSXin Li        self.assertEqual(patches2[2].version_range, {"from": 4, "until": 5})
312*760c253cSXin Li
313*760c253cSXin Li    def test_remove_old_patches(self):
314*760c253cSXin Li        patches = [
315*760c253cSXin Li            {"rel_patch_path": "foo.patch"},
316*760c253cSXin Li            {
317*760c253cSXin Li                "rel_patch_path": "bar.patch",
318*760c253cSXin Li                "version_range": {
319*760c253cSXin Li                    "from": 1,
320*760c253cSXin Li                },
321*760c253cSXin Li            },
322*760c253cSXin Li            {
323*760c253cSXin Li                "rel_patch_path": "baz.patch",
324*760c253cSXin Li                "version_range": {
325*760c253cSXin Li                    "until": 1,
326*760c253cSXin Li                },
327*760c253cSXin Li            },
328*760c253cSXin Li        ]
329*760c253cSXin Li
330*760c253cSXin Li        tempdir = self.make_tempdir()
331*760c253cSXin Li        patches_json = tempdir / "PATCHES.json"
332*760c253cSXin Li        with patches_json.open("w", encoding="utf-8") as f:
333*760c253cSXin Li            json.dump(patches, f)
334*760c253cSXin Li
335*760c253cSXin Li        removed_paths = pu.remove_old_patches(
336*760c253cSXin Li            svn_version=10, patches_json=patches_json
337*760c253cSXin Li        )
338*760c253cSXin Li        self.assertEqual(removed_paths, [tempdir / "baz.patch"])
339*760c253cSXin Li        expected_patches = [
340*760c253cSXin Li            x for x in patches if x["rel_patch_path"] != "baz.patch"
341*760c253cSXin Li        ]
342*760c253cSXin Li        self.assertEqual(
343*760c253cSXin Li            json.loads(patches_json.read_text(encoding="utf-8")),
344*760c253cSXin Li            expected_patches,
345*760c253cSXin Li        )
346*760c253cSXin Li
347*760c253cSXin Li    @staticmethod
348*760c253cSXin Li    def _default_json_dict():
349*760c253cSXin Li        return {
350*760c253cSXin Li            "metadata": {
351*760c253cSXin Li                "title": "hello world",
352*760c253cSXin Li            },
353*760c253cSXin Li            "platforms": ["a"],
354*760c253cSXin Li            "rel_patch_path": "x/y/z",
355*760c253cSXin Li            "version_range": {
356*760c253cSXin Li                "from": 4,
357*760c253cSXin Li                "until": 9,
358*760c253cSXin Li            },
359*760c253cSXin Li        }
360*760c253cSXin Li
361*760c253cSXin Li    @staticmethod
362*760c253cSXin Li    def _mock_dir(path: str = "a/b/c"):
363*760c253cSXin Li        workdir = Path(path)
364*760c253cSXin Li        workdir = mock.MagicMock(workdir)
365*760c253cSXin Li        workdir.is_dir = lambda: True
366*760c253cSXin Li        workdir.joinpath = lambda x: Path(path).joinpath(x)
367*760c253cSXin Li        workdir.__truediv__ = lambda self, x: self.joinpath(x)
368*760c253cSXin Li        return workdir
369*760c253cSXin Li
370*760c253cSXin Li
371*760c253cSXin Li_EXAMPLE_PATCH = """
372*760c253cSXin Lidiff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
373*760c253cSXin Liindex 5620a543438..099eb769ca5 100644
374*760c253cSXin Li--- a/clang/lib/Driver/ToolChains/Clang.cpp
375*760c253cSXin Li+++ b/clang/lib/Driver/ToolChains/Clang.cpp
376*760c253cSXin Li@@ -3995,8 +3995,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
377*760c253cSXin Li       Args.hasArg(options::OPT_dA))
378*760c253cSXin Li     CmdArgs.push_back("-masm-verbose");
379*760c253cSXin Li
380*760c253cSXin Li-  if (!TC.useIntegratedAs())
381*760c253cSXin Li+  if (!TC.useIntegratedAs()) {
382*760c253cSXin Li     CmdArgs.push_back("-no-integrated-as");
383*760c253cSXin Li+    CmdArgs.push_back("-mllvm");
384*760c253cSXin Li+    CmdArgs.push_back("-enable-call-graph-profile-sort=false");
385*760c253cSXin Li+  }
386*760c253cSXin Li
387*760c253cSXin Li   if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
388*760c253cSXin Li     CmdArgs.push_back("-mdebug-pass");
389*760c253cSXin Lidiff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
390*760c253cSXin Liindex c5fd68299eb..4c6e15eeeb9 100644
391*760c253cSXin Li--- a/llvm/lib/Passes/PassBuilder.cpp
392*760c253cSXin Li+++ b/llvm/lib/Passes/PassBuilder.cpp
393*760c253cSXin Li@@ -212,6 +212,10 @@ static cl::opt<bool>
394*760c253cSXin Li     EnableCHR("enable-chr-npm", cl::init(true), cl::Hidden,
395*760c253cSXin Li               cl::desc("Enable control height reduction optimization (CHR)"));
396*760c253cSXin Li
397*760c253cSXin Li+static cl::opt<bool> EnableCallGraphProfileSort(
398*760c253cSXin Li+    "enable-call-graph-profile-sort", cl::init(true), cl::Hidden,
399*760c253cSXin Li+    cl::desc("Enable call graph profile pass for the new PM (default = on)"));
400*760c253cSXin Li+
401*760c253cSXin Li extern cl::opt<bool> EnableHotColdSplit;
402*760c253cSXin Li extern cl::opt<bool> EnableOrderFileInstrumentation;
403*760c253cSXin Li
404*760c253cSXin Li@@ -939,7 +943,8 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline(
405*760c253cSXin Li   // Add the core optimizing pipeline.
406*760c253cSXin Li   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM)));
407*760c253cSXin Li
408*760c253cSXin Li-  MPM.addPass(CGProfilePass());
409*760c253cSXin Li+  if (EnableCallGraphProfileSort)
410*760c253cSXin Li+    MPM.addPass(CGProfilePass());
411*760c253cSXin Li
412*760c253cSXin Li   // Now we need to do some global optimization transforms.
413*760c253cSXin Li   // FIXME: It would seem like these should come first in the optimization
414*760c253cSXin Li"""
415*760c253cSXin Li
416*760c253cSXin Liif __name__ == "__main__":
417*760c253cSXin Li    unittest.main()
418