From: Nikodemus S. <nik...@ra...> - 2008-11-04 18:23:33
Attachments:
0001-fix-bug-430.patch
|
The attached patch fixes bug 430: nested structure constructors do not stack allocate, and more generally makes stack allocation from inlined functions work properly: (declaim (inline fii)) (defun fii (&optional (a 1) (b 2)) (list a b)) (defun fii-it (a b) (let ((fii (fii (fii a b) (fii b a)))) (declare (dynamic-extent fii)) (print fii) nil)) FII-IT can stack allocate the lists with this patch. The patch breaks one of the current test-cases: (defun-with-dx let-converted-vars-dx-allocated-bug (x y z) (let* ((a (list x y z)) (b (list x y z)) (c (list a b))) (declare (dynamic-extent c)) (values (first c) (second c)))) (with-test (:name :let-converted-vars-dx-allocated-bug) (multiple-value-bind (i j) (let-converted-vars-dx-allocated-bug 1 2 3) (assert (and (equal i j) (equal i (list 1 2 3)))))) ...which I don't think is actually a valid test-case -- even though I'm the one who wrote it in the first place. If returned values are A and B instead, it works as expected. It is not obvious to me at the moment how to retain both this behaviour, and allow stack allocation in the inline case as above. Input on the validity of this test-case much appreciated, as well as any insight on how to deal with inline functions in cases like FII-IT without breaking this case. Executive summary: * Allow USE-GOOD-FOR-DX-P to inspect COMBINATIONs with CLAMBDA functionals: if the return value of the function always originates from a known DX-capable combination, and the arguments of the original combination are used only by the DX-capable combination, consider the combination good for DX. * Allow USE-GOOD-FOR-DX-P to inspect REFs to LAMBDA-VARs: if the var has no other REFs, is never set, is bound by a single-value combination, and the LVAR it gets it's value from in the combination is good for DX ... then the REF is good for DX as well. Code reviews and more hairy test-cases welcome. Cheers, -- Nikodemus |
From: Christophe R. <cs...@ca...> - 2008-11-04 20:42:25
|
"Nikodemus Siivola" <nik...@ra...> writes: > The patch breaks one of the current test-cases: > > (defun-with-dx let-converted-vars-dx-allocated-bug (x y z) > (let* ((a (list x y z)) > (b (list x y z)) > (c (list a b))) > (declare (dynamic-extent c)) > (values (first c) (second c)))) > > (with-test (:name :let-converted-vars-dx-allocated-bug) > (multiple-value-bind (i j) (let-converted-vars-dx-allocated-bug 1 2 3) > (assert (and (equal i j) > (equal i (list 1 2 3)))))) > > ...which I don't think is actually a valid test-case -- even though > I'm the one who wrote it in the first place. Sorry, why is it not a valid test case? Best, Christophe |
From: Nikodemus S. <nik...@ra...> - 2008-11-04 21:02:59
|
On Tue, Nov 4, 2008 at 10:42 PM, Christophe Rhodes <cs...@ca...> wrote: > "Nikodemus Siivola" <nik...@ra...> writes: > >> The patch breaks one of the current test-cases: >> >> (defun-with-dx let-converted-vars-dx-allocated-bug (x y z) >> (let* ((a (list x y z)) >> (b (list x y z)) >> (c (list a b))) >> (declare (dynamic-extent c)) >> (values (first c) (second c)))) >> >> (with-test (:name :let-converted-vars-dx-allocated-bug) >> (multiple-value-bind (i j) (let-converted-vars-dx-allocated-bug 1 2 3) >> (assert (and (equal i j) >> (equal i (list 1 2 3)))))) >> >> ...which I don't think is actually a valid test-case -- even though >> I'm the one who wrote it in the first place. > > Sorry, why is it not a valid test case? *rereads the spec again* Let me rephrase that as "which I'm not sure is a valid test-case". The interpretation of otherwise inaccessible makes my head hurt. In the test case _as_written_, A and B are accessible only via C, as there are no references to A and B except for the ones in the (LIST A B) call. Hence, "otherwise inaccessible". ...but I can (now again, as I presumably did when I wrote the test) *also* see how lists A and B can be considered otherwise accessible as well: they are bound to lexical variables which just "accidentally" are accessed only in the constructor for C -- but could be accessed anywhere. *argh* I'll spend some more time with this tomorrow to see if I can come up with something fiendishly clever to sidestep this. Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2008-11-07 15:35:16
|
On Tue, Nov 4, 2008 at 11:02 PM, Nikodemus Siivola <nik...@ra...> wrote: > *argh* I'll spend some more time with this tomorrow to see if I can > come up with something fiendishly clever to sidestep this. I think I have a solution, after all: mark clambdas that are introduced by the system as such, and treat their bindings transparently WRT nested DX analysis. It does TRT (according to the more conservative interpretation of "otherwise accessible") for both the earlier test-case and (defun aux-test (x y z &aux (a (list x y z))) (let ((c (list a))) (declare (dynamic-extent c)) (values (first c)))) (defun rest-test (&rest args) (let ((c (list args))) (declare (dynamic-extent c)) (values (first c)))) in addition to allowing DX for the hairy nestings without such ambiguities, but I need to still make sure it does that by design and not by accident. Nestings from inlined functions also need more work, as my current version cannot yet stack allocate the inner list here: (declaim (inline hard)) (defun hard (x y z) (list (list x y z))) (defun harder (i j k) (let ((x (hard i j k))) (declare (dynamic-extent x)) (print x) nil) Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2008-12-11 17:35:48
Attachments:
0001-fix-bug-430.patch
|
On Fri, Nov 7, 2008 at 5:35 PM, Nikodemus Siivola <nik...@ra...> wrote: > I think I have a solution, after all: mark clambdas that are > introduced by the system as such, and treat their bindings > transparently WRT nested DX analysis. > > It does TRT (according to the more conservative interpretation of > "otherwise accessible") for both the earlier test-case and > > (defun aux-test (x y z &aux (a (list x y z))) > (let ((c (list a))) > (declare (dynamic-extent c)) > (values (first c)))) > > (defun rest-test (&rest args) > (let ((c (list args))) > (declare (dynamic-extent c)) > (values (first c)))) > > in addition to allowing DX for the hairy nestings without such > ambiguities, but I need to still make sure it does that by design and > not by accident. I haven't yet verified this, but FWIW my current work is attached. The problem outlined below remains. > Nestings from inlined functions also need more work, as my current > version cannot yet stack allocate the inner list here: > > (declaim (inline hard)) > (defun hard (x y z) > (list (list x y z))) > > (defun harder (i j k) > (let ((x (hard i j k))) > (declare (dynamic-extent x)) > (print x) > nil) Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2008-12-12 13:09:22
|
On Thu, Dec 11, 2008 at 7:35 PM, Nikodemus Siivola <nik...@ra...> wrote: > I haven't yet verified this, but FWIW my current work is attached. The > problem outlined below remains. Having convinced myself that the workingness was just not a happy accident, I've committed this as 1.0.23.38. In other words: nested structure constructors are now able to stack allocate. Cheers, -- Nikodemus |