Skip to content

Commit 3d91c9c

Browse files
committed
perf: infer better IR types to reduce refcounting
1 parent 72ddc47 commit 3d91c9c

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

src/Lean/Compiler/IR/ToIR.lean

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ open Lean.Compiler (LCNF.Alt LCNF.Arg LCNF.Code LCNF.Decl LCNF.DeclValue LCNF.LC
1919

2020
namespace ToIR
2121

22+
/--
23+
Marks an extern definition to be guaranteed to always return tagged values.
24+
This information is used to optimize reference counting in the compiler.
25+
-/
26+
@[builtin_doc]
27+
builtin_initialize taggedReturnAttr : TagAttribute ←
28+
registerTagAttribute `tagged_return "mark extern definition to always return tagged values"
29+
2230
structure BuilderState where
2331
vars : Std.HashMap FVarId Arg := {}
2432
joinPoints : Std.HashMap FVarId JoinPointId := {}
@@ -334,12 +342,20 @@ where resultTypeForArity (type : Lean.Expr) (arity : Nat) : Lean.Expr :=
334342

335343
def lowerDecl (d : LCNF.Decl) : M (Option Decl) := do
336344
let params ← d.params.mapM lowerParam
337-
let resultType ← lowerResultType d.type d.params.size
345+
let mut resultType ← lowerResultType d.type d.params.size
346+
let taggedReturn := taggedReturnAttr.hasTag (← getEnv) d.name
338347
match d.value with
339348
| .code code =>
349+
if taggedReturn then
350+
throwError m!"Error while compiling function '{d.name}': @[tagged_return] is only valid for extern declarations"
340351
let body ← lowerCode code
341352
pure <| some <| .fdecl d.name params resultType body {}
342353
| .extern externAttrData =>
354+
if taggedReturn then
355+
if resultType.isScalar then
356+
throwError m!"@[tagged_return] on function '{d.name}' with scalar return type {resultType}"
357+
else
358+
resultType := .tagged
343359
if externAttrData.entries.isEmpty then
344360
-- TODO: This matches the behavior of the old compiler, but we should
345361
-- find a better way to handle this.

src/stdlib_flags.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "util/options.h"
22

3+
// update thy
4+
35
namespace lean {
46
options get_default_options() {
57
options opts;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/-! This test asserts the basic behavior of the tagged_return attribute -/
2+
3+
@[extern "mytest", tagged_return]
4+
opaque test (a : Nat) : Nat
5+
6+
/--
7+
trace: [Compiler.IR] [result]
8+
def useTest (x_1 : tobj) (x_2 : @& tobj) : tobj :=
9+
inc x_1;
10+
let x_3 : tagged := test x_1;
11+
let x_4 : tobj := Nat.add x_3 x_1;
12+
dec x_1;
13+
let x_5 : tobj := Nat.add x_4 x_2;
14+
dec x_4;
15+
ret x_5
16+
def useTest._boxed (x_1 : tobj) (x_2 : tobj) : tobj :=
17+
let x_3 : tobj := useTest x_1 x_2;
18+
dec x_2;
19+
ret x_3
20+
-/
21+
#guard_msgs in
22+
set_option trace.compiler.ir.result true in
23+
def useTest (a b : Nat) :=
24+
(test a + a) + b
25+
26+
/--
27+
error: Error while compiling function 'illegal1': @[tagged_return] is only valid for extern declarations
28+
-/
29+
#guard_msgs in
30+
@[tagged_return]
31+
opaque illegal1 (a : Nat) : Nat
32+
33+
/-- error: @[tagged_return] on function 'illegal2' with scalar return type u8 -/
34+
#guard_msgs in
35+
@[extern "mytest", tagged_return]
36+
opaque illegal2 (a : Nat) : UInt8

0 commit comments

Comments
 (0)