Да, ваше решение оптимально, потому что оно будет вызывать предикат sum / 2 ровно один раз для каждого узла в дереве (и вы просто не сможете делать меньше вызовов). Нет, вы можете сделать его рекурсивным, реализовав стек самостоятельно с помощью аккумулятора.
Вот пример (не тестировался). Предикат уплощения может быть интегрирован с суммой, но здесь они отличаются для ясности (оба являются хвостово-рекурсивными):
flatten([], Acc, Acc).
flatten([void|ToGo], Acc, Result) :-
flatten(ToGo, Acc, Result).
flatten([t(V,L,R)|ToGo], Acc, Result) :-
flatten([L,R|ToGo], [t(V,L,R)|Acc], Result).
flatten(Root, Result) :-
flatten([Root], [], Result).
sum([], Result, Result).
sum([t(V,_,_)|ToGo], Acc, Result) :-
NewAcc is Acc+V,
sum(ToGo, NewAcc, Result).
sum(Tree, Result) :-
flatten(Tree, FlatTree),
sum(FlatTree, 0, Result).