Open ChuanqiXu9 opened 1 year ago
@llvm/issue-subscribers-c-20
@llvm/issue-subscribers-clang-frontend
CC folks who might know where the main culprit is or may know how the determine it @erichkeane @zygoloid @tbaederr
I don't have much familiarity with the consteval code, @AaronBallman and @Fznamznon are the two who have been spending the most time doing that lately.
I don't know if this is helpful, but I ran the example with -ftime-trace and put the .json into speedscope, and interestingly it's not that something is really slower but rather it's simply computed twice.
The constexpr case has
EvaluateAsInitializer {"detail":"Fibonacci::Cache"}
> Frontend
> ExecuteCompiler
The consteval case has
EvaluateAsConstantExpr {"detail":"<Fib.cpp:39:19, col:33>"}
> InstantiateFunction {"detail":"Fibonacci::Compute<Fibonacci::DefaultStrategy>"}
> Frontend
> ExecuteCompiler
as well as
EvaluateAsConstantExpr {"detail":"<Fib.cpp:39:19, col:33>"}
> Frontend
> ExecuteCompiler
both taking roughly the same time as the single constexpr case. So really, only EvaluateAsConstantExpr is performed twice which doubles the compile time.
Seems similar to #61425
Agreed, this seems to be a duplicate of #61425.
I don't think this is a duplicate. #61425 would cover the repeated calls to Recursive
not being cached like GCC does, but I don't think that's what this bug is about -- I think this bug is about an immediate invocation being evaluated twice. And that's a real bug -- an immediate invocation will eventually be able to have side effects, such as emitting messages at compile time or generating AST nodes, once more consteval
primitives are added to the standard library, so we really need to only evaluate them once.
Presumably the issue here is that the constant evaluator is stepping into ConstantExpr
s rather than picking up and using their stored value.
Oh, thank you for observing that! I've reopened the issue.
@zygoloid Thanks!
RemoveNestedImmediateInvocation
uses a TreeTransform. I think maybe this should be replaced with a recursive visitor of some sort? Why are we using a transform when all we want to do is to remove entries from ReferenceToConsteval
? There TreeTranform does appear to get rid of all ConstantExpr
nodes, so i suspect this is the source of the bug.
IIUC the TreeTransform
is only used in cases like
consteval int id(int n) { return n; }
int x = id(id(2));
where we'd otherwise have two nested ConstantExpr
nodes and want only one (because the inner one isn't a full-expression).
The way I think this was supposed to work is that we build the inner call and its ConstantExpr
wrapper, then build the outer call and its ConstantExpr
wrapper, then at the end of the full-expression if we have more than one ConstantExpr
we do a TreeTransform
to strip out all the nested ones, and finally compute and store the constant value for any that remain.
The reproducer:
Let's run:
in my computer it shows:
But if I change
Recursive
intoconsteval
, the result will be:it shows now it takes double times to compile the source.