Skip to content

Commit 5e91a09

Browse files
kddnewtonmeta-codesync[bot]
authored andcommitted
Elide Decref codegen for known-immortal objects
Summary: The JIT already has infrastructure to skip Incref/Decref for objects known to be immortal at compile time, but outputType() returned types with unknown mortality for several operations that provably produce immortal singletons (True, False, None). This caused unnecessary Decref sequences (7-11 instructions each) to be emitted. Change outputType() to return TImmortalBool for Compare<In/NotIn>, UnaryOp<Not>, FloatCompare, LongCompare, UnicodeCompare, and PrimitiveBoxBool. Return TImmortalNoneType for ListExtend and TOptImmortalNoneType for InitialYield. These are safe because the JIT runtime helpers (JITRT_SequenceContains, JITRT_UnaryNot, etc.) all explicitly return Py_True/Py_False/Py_None. The downstream refcount insertion pass automatically treats ImmortalBool/ImmortalNoneType as uncounted, eliding all Incref/Decref operations. Reviewed By: DinoV Differential Revision: D103079581 fbshipit-source-id: 5752552c489fca0af963e195bd68712addcacb5f
1 parent 85d8bc8 commit 5e91a09

6 files changed

Lines changed: 432 additions & 14 deletions

File tree

cinderx/Jit/hir/pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ Type outputType(
303303
case Opcode::kGetTuple:
304304
return TTupleExact;
305305
case Opcode::kInitialYield:
306-
return TOptNoneType;
306+
return TOptImmortalNoneType;
307307
case Opcode::kLoadArg: {
308308
auto& loadarg = static_cast<const LoadArg&>(instr);
309309
return loadarg.type();
@@ -366,7 +366,7 @@ Type outputType(
366366
// we should get rid of this extra layer and deal with the int return value
367367
// directly.
368368
case Opcode::kListExtend:
369-
return TNoneType;
369+
return TImmortalNoneType;
370370

371371
case Opcode::kListAppend:
372372
case Opcode::kMergeSetUnpack:

cinderx/RuntimeTests/hir_tests/all_passes_test.txt

Lines changed: 285 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,149 @@ fun jittestmodule:test {
685685
}
686686
}
687687
--- Test Name ---
688+
CompareInBranchElidesDecref
689+
--- Input ---
690+
def test(x, y):
691+
if x in y:
692+
return x
693+
return y
694+
--- Expected 3.12 ---
695+
fun jittestmodule:test {
696+
bb 0 {
697+
v7:Object = LoadArg<0; "x">
698+
v8:Object = LoadArg<1; "y">
699+
LoadFrame
700+
UpdatePrevInstr<idx:0 line_no:1: no parent>
701+
v10:CInt32 = LoadEvalBreaker
702+
CondBranch<4, 3> v10
703+
}
704+
705+
bb 4 (preds 0) {
706+
v11:CInt32 = RunPeriodicTasks {
707+
LiveValues<2> b:v7 b:v8
708+
FrameState {
709+
CurInstrOffset 0
710+
Locals<2> v7 v8
711+
}
712+
}
713+
Branch<3>
714+
}
715+
716+
bb 3 (preds 0, 4) {
717+
v14:ImmortalBool = Compare<In> v7 v8 {
718+
LiveValues<2> b:v7 b:v8
719+
FrameState {
720+
CurInstrOffset 6
721+
Locals<2> v7 v8
722+
}
723+
}
724+
v16:ImmortalBool[True] = LoadConst<ImmortalBool[True]>
725+
v17:CBool = PrimitiveCompare<Equal> v14 v16
726+
CondBranch<1, 2> v17
727+
}
728+
729+
bb 1 (preds 3) {
730+
Incref v7
731+
Return v7
732+
}
733+
734+
bb 2 (preds 3) {
735+
Incref v8
736+
Return v8
737+
}
738+
}
739+
--- Expected 3.14 ---
740+
fun jittestmodule:test {
741+
bb 0 {
742+
v8:Object = LoadArg<0; "x">
743+
v9:Object = LoadArg<1; "y">
744+
LoadFrame
745+
UpdatePrevInstr<idx:0 line_no:1: no parent>
746+
v11:CInt64 = LoadEvalBreaker
747+
CondBranch<4, 3> v11
748+
}
749+
750+
bb 4 (preds 0) {
751+
v12:CInt32 = RunPeriodicTasks {
752+
LiveValues<2> b:v8 b:v9
753+
FrameState {
754+
CurInstrOffset 0
755+
Locals<2> v8 v9
756+
}
757+
}
758+
Branch<3>
759+
}
760+
761+
bb 3 (preds 0, 4) {
762+
v15:ImmortalBool = Compare<In> v8 v9 {
763+
LiveValues<2> b:v8 b:v9
764+
FrameState {
765+
CurInstrOffset 4
766+
Locals<2> v8 v9
767+
}
768+
}
769+
v16:ImmortalBool[True] = LoadConst<ImmortalBool[True]>
770+
v17:CBool = PrimitiveCompare<Equal> v15 v16
771+
CondBranch<1, 2> v17
772+
}
773+
774+
bb 1 (preds 3) {
775+
Incref v8
776+
Return v8
777+
}
778+
779+
bb 2 (preds 3) {
780+
Incref v9
781+
Return v9
782+
}
783+
}
784+
--- Expected 3.15 ---
785+
fun jittestmodule:test {
786+
bb 0 {
787+
v8:Object = LoadArg<0; "x">
788+
v9:Object = LoadArg<1; "y">
789+
LoadFrame
790+
v11:CInt64 = LoadEvalBreaker
791+
CondBranch<4, 3> v11
792+
}
793+
794+
bb 4 (preds 0) {
795+
UpdatePrevInstr<idx:0 line_no:1: no parent>
796+
v12:CInt32 = RunPeriodicTasks {
797+
LiveValues<2> b:v8 b:v9
798+
FrameState {
799+
CurInstrOffset 0
800+
Locals<2> v8 v9
801+
}
802+
}
803+
Branch<3>
804+
}
805+
806+
bb 3 (preds 0, 4) {
807+
UpdatePrevInstr<idx:3 line_no:2: no parent>
808+
v15:ImmortalBool = Compare<In> v8 v9 {
809+
LiveValues<2> b:v8 b:v9
810+
FrameState {
811+
CurInstrOffset 6
812+
Locals<2> v8 v9
813+
}
814+
}
815+
v16:ImmortalBool[True] = LoadConst<ImmortalBool[True]>
816+
v17:CBool = PrimitiveCompare<Equal> v15 v16
817+
CondBranch<1, 2> v17
818+
}
819+
820+
bb 1 (preds 3) {
821+
Incref v8
822+
Return v8
823+
}
824+
825+
bb 2 (preds 3) {
826+
Incref v9
827+
Return v9
828+
}
829+
}
830+
--- Test Name ---
688831
CompareNotInReturnsBool
689832
--- Input ---
690833
def test(x, y):
@@ -966,7 +1109,7 @@ fun jittestmodule:test {
9661109
bb 0 {
9671110
LoadFrame
9681111
v16:Nullptr = LoadConst<Nullptr>
969-
v17:OptNoneType = InitialYield {
1112+
v17:OptImmortalNoneType = InitialYield {
9701113
LiveValues<1> unc:v16
9711114
FrameState {
9721115
CurInstrOffset 0
@@ -1073,7 +1216,7 @@ fun jittestmodule:test {
10731216
bb 0 {
10741217
LoadFrame
10751218
v16:Nullptr = LoadConst<Nullptr>
1076-
v17:OptNoneType = InitialYield {
1219+
v17:OptImmortalNoneType = InitialYield {
10771220
LiveValues<1> unc:v16
10781221
FrameState {
10791222
CurInstrOffset 2
@@ -1181,7 +1324,7 @@ fun jittestmodule:test {
11811324
LoadFrame
11821325
v16:Nullptr = LoadConst<Nullptr>
11831326
UpdatePrevInstr<idx:1 line_no:1: no parent>
1184-
v17:OptNoneType = InitialYield {
1327+
v17:OptImmortalNoneType = InitialYield {
11851328
LiveValues<1> unc:v16
11861329
FrameState {
11871330
CurInstrOffset 2
@@ -1730,4 +1873,143 @@ fun jittestmodule:test {
17301873
Return v22
17311874
}
17321875
}
1876+
--- Test Name ---
1877+
ListExtendElidesNoneDecref
1878+
--- Input ---
1879+
def test(x, y):
1880+
result = [*x]
1881+
return y
1882+
--- Expected 3.12 ---
1883+
fun jittestmodule:test {
1884+
bb 0 {
1885+
v8:Object = LoadArg<0; "x">
1886+
v9:Object = LoadArg<1; "y">
1887+
LoadFrame
1888+
v11:Nullptr = LoadConst<Nullptr>
1889+
UpdatePrevInstr<idx:0 line_no:1: no parent>
1890+
v12:CInt32 = LoadEvalBreaker
1891+
CondBranch<2, 1> v12
1892+
}
1893+
1894+
bb 2 (preds 0) {
1895+
v13:CInt32 = RunPeriodicTasks {
1896+
LiveValues<3> b:v8 b:v9 unc:v11
1897+
FrameState {
1898+
CurInstrOffset 0
1899+
Locals<3> v8 v9 v11
1900+
}
1901+
}
1902+
Branch<1>
1903+
}
1904+
1905+
bb 1 (preds 0, 2) {
1906+
v17:MortalListExact = MakeList<0> {
1907+
LiveValues<3> b:v8 b:v9 unc:v11
1908+
FrameState {
1909+
CurInstrOffset 2
1910+
Locals<3> v8 v9 v11
1911+
}
1912+
}
1913+
v18:ImmortalNoneType = ListExtend v17 v8 {
1914+
LiveValues<4> b:v8 b:v9 unc:v11 o:v17
1915+
FrameState {
1916+
CurInstrOffset 6
1917+
Locals<3> v8 v9 v11
1918+
Stack<1> v17
1919+
}
1920+
}
1921+
Decref v17
1922+
Incref v9
1923+
Return v9
1924+
}
1925+
}
1926+
--- Expected 3.14 ---
1927+
fun jittestmodule:test {
1928+
bb 0 {
1929+
v8:Object = LoadArg<0; "x">
1930+
v9:Object = LoadArg<1; "y">
1931+
LoadFrame
1932+
v11:Nullptr = LoadConst<Nullptr>
1933+
UpdatePrevInstr<idx:0 line_no:1: no parent>
1934+
v12:CInt64 = LoadEvalBreaker
1935+
CondBranch<2, 1> v12
1936+
}
1937+
1938+
bb 2 (preds 0) {
1939+
v13:CInt32 = RunPeriodicTasks {
1940+
LiveValues<3> b:v8 b:v9 unc:v11
1941+
FrameState {
1942+
CurInstrOffset 0
1943+
Locals<3> v8 v9 v11
1944+
}
1945+
}
1946+
Branch<1>
1947+
}
1948+
1949+
bb 1 (preds 0, 2) {
1950+
v17:MortalListExact = MakeList<0> {
1951+
LiveValues<3> b:v8 b:v9 unc:v11
1952+
FrameState {
1953+
CurInstrOffset 2
1954+
Locals<3> v8 v9 v11
1955+
}
1956+
}
1957+
v18:ImmortalNoneType = ListExtend v17 v8 {
1958+
LiveValues<4> b:v8 b:v9 unc:v11 o:v17
1959+
FrameState {
1960+
CurInstrOffset 6
1961+
Locals<3> v8 v9 v11
1962+
Stack<1> v17
1963+
}
1964+
}
1965+
Decref v17
1966+
Incref v9
1967+
Return v9
1968+
}
1969+
}
1970+
--- Expected 3.15 ---
1971+
fun jittestmodule:test {
1972+
bb 0 {
1973+
v8:Object = LoadArg<0; "x">
1974+
v9:Object = LoadArg<1; "y">
1975+
LoadFrame
1976+
v11:Nullptr = LoadConst<Nullptr>
1977+
v12:CInt64 = LoadEvalBreaker
1978+
CondBranch<2, 1> v12
1979+
}
1980+
1981+
bb 2 (preds 0) {
1982+
UpdatePrevInstr<idx:0 line_no:1: no parent>
1983+
v13:CInt32 = RunPeriodicTasks {
1984+
LiveValues<3> b:v8 b:v9 unc:v11
1985+
FrameState {
1986+
CurInstrOffset 0
1987+
Locals<3> v8 v9 v11
1988+
}
1989+
}
1990+
Branch<1>
1991+
}
1992+
1993+
bb 1 (preds 0, 2) {
1994+
v17:MortalListExact = MakeList<0> {
1995+
LiveValues<3> b:v8 b:v9 unc:v11
1996+
FrameState {
1997+
CurInstrOffset 4
1998+
Locals<3> v8 v9 v11
1999+
}
2000+
}
2001+
v18:ImmortalNoneType = ListExtend v17 v8 {
2002+
LiveValues<4> b:v8 b:v9 unc:v11 o:v17
2003+
FrameState {
2004+
CurInstrOffset 8
2005+
Locals<3> v8 v9 v11
2006+
Stack<1> v17
2007+
}
2008+
}
2009+
UpdatePrevInstr<idx:7 line_no:3: no parent>
2010+
Decref v17
2011+
Incref v9
2012+
Return v9
2013+
}
2014+
}
17332015
--- End ---

cinderx/RuntimeTests/hir_tests/builtin_load_method_elimination_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ fun jittestmodule:test {
792792
v14:Func = LoadCurrentFunc
793793
LoadFrame
794794
Snapshot
795-
v15:OptNoneType = InitialYield {
795+
v15:OptImmortalNoneType = InitialYield {
796796
FrameState {
797797
CurInstrOffset 0
798798
}
@@ -893,7 +893,7 @@ fun jittestmodule:test {
893893
v14:Func = LoadCurrentFunc
894894
LoadFrame
895895
Snapshot
896-
v15:OptNoneType = InitialYield {
896+
v15:OptImmortalNoneType = InitialYield {
897897
FrameState {
898898
CurInstrOffset 2
899899
}
@@ -994,7 +994,7 @@ fun jittestmodule:test {
994994
v15:Func = LoadCurrentFunc
995995
LoadFrame
996996
Snapshot
997-
v16:OptNoneType = InitialYield {
997+
v16:OptImmortalNoneType = InitialYield {
998998
FrameState {
999999
CurInstrOffset 2
10001000
}

cinderx/RuntimeTests/hir_tests/inliner_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ fun jittestmodule:test {
529529
}
530530
Snapshot
531531
v17:MortalTupleExact[tuple:0xdeadbeef] = LoadConst<MortalTupleExact[tuple:0xdeadbeef]>
532-
v18:NoneType = ListExtend v16 v17 {
532+
v18:ImmortalNoneType = ListExtend v16 v17 {
533533
FrameState {
534534
CurInstrOffset 6
535535
Locals<1> v12
@@ -619,7 +619,7 @@ fun jittestmodule:test {
619619
}
620620
Snapshot
621621
v17:MortalTupleExact[tuple:0xdeadbeef] = LoadConst<MortalTupleExact[tuple:0xdeadbeef]>
622-
v18:NoneType = ListExtend v16 v17 {
622+
v18:ImmortalNoneType = ListExtend v16 v17 {
623623
FrameState {
624624
CurInstrOffset 6
625625
Locals<1> v12
@@ -710,7 +710,7 @@ fun jittestmodule:test {
710710
}
711711
Snapshot
712712
v17:MortalTupleExact[tuple:0xdeadbeef] = LoadConst<MortalTupleExact[tuple:0xdeadbeef]>
713-
v18:NoneType = ListExtend v16 v17 {
713+
v18:ImmortalNoneType = ListExtend v16 v17 {
714714
FrameState {
715715
CurInstrOffset 8
716716
Locals<1> v12

0 commit comments

Comments
 (0)