With this patch, simplifyBinOp in visitBinaryInst may return
PoisonValue. So this patch also introduce a poison tag to ValueLattice
to handle poison constant.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
This only makes a difference when the binop returns a poison result, right? I think it's unfortunate that this ends up replacing that with an undef value.
I think it would be good to introduce a new lattice value for poison, which allows us to explicitly represent this and avoid refining poison to undef. Especially in conjunction with D153718, which is kind of weird in we claim no undefs but the result is represented as undef.
Exactly. Replace a poison value with an undef value is not a good idea, because As LangRef says, PoisonValue is stronger than UndefValue, it enables more optimizations. But actually, I really don't understand that, or in other words, I can't find an example to convince myself. Do you @nikic know that or do you mind telling me the answer? :)
I think it would be good to introduce a new lattice value for poison, which allows us to explicitly represent this and avoid refining poison to undef. Especially in conjunction with D153718, which is kind of weird in we claim no undefs but the result is represented as under.
This is a good idea. Or I also had an idea that we don't need the undef enum in ValueLattice, because no matter UndefValue or PoisonValue, they are all constant. And when we visit instructions in SCCPSolver, we should do instructionsimplify for instructions that one of their operands is constant. If we want to judge if a valuelattice is undef, we can just judge like isa<UndefValue>(ConstVal). What's your @nikic opinion?
For example and i32 %x, poison is poison, but and i32 %x, undef is not undef (it would be folded to i32 0).
I think it would be good to introduce a new lattice value for poison, which allows us to explicitly represent this and avoid refining poison to undef. Especially in conjunction with D153718, which is kind of weird in we claim no undefs but the result is represented as under.
This is a good idea. Or I also had an idea that we don't need the undef enum in ValueLattice, because no matter UndefValue or PoisonValue, they are all constant. And when we visit instructions in SCCPSolver, we should do instructionsimplify for instructions that one of their operands is constant. If we want to judge if a valuelattice is undef, we can just judge like isa<UndefValue>(ConstVal). What's your @nikic opinion?
I think the reason for the separate undef state is to make sure it does not accidentally get treated like a constant. The core problem is that SCCP allows a lattice transition undef -> C (which basically only exists to support phi nodes with undef operands). So if you initially folded some operation using undef as op(undef) = C2 (which makes an implicit choice of undef) and then transition undef -> C, then op(C) = C3 where possibly C2 != C3. This would violate the lattice structure.
Thanks for your detailed explanation!
I think it would be good to introduce a new lattice value for poison, which allows us to explicitly represent this and avoid refining poison to undef. Especially in conjunction with D153718, which is kind of weird in we claim no undefs but the result is represented as under.
This is a good idea. Or I also had an idea that we don't need the undef enum in ValueLattice, because no matter UndefValue or PoisonValue, they are all constant. And when we visit instructions in SCCPSolver, we should do instructionsimplify for instructions that one of their operands is constant. If we want to judge if a valuelattice is undef, we can just judge like isa<UndefValue>(ConstVal). What's your @nikic opinion?
I think the reason for the separate undef state is to make sure it does not accidentally get treated like a constant. The core problem is that SCCP allows a lattice transition undef -> C (which basically only exists to support phi nodes with undef operands). So if you initially folded some operation using undef as op(undef) = C2 (which makes an implicit choice of undef) and then transition undef -> C, then op(C) = C3 where possibly C2 != C3. This would violate the lattice structure.
This is indeed the problem. Maybe we can use SimplifyQuery(DL).getWithoutUndef() as a query wrapper to avoid this situation.
llvm/lib/Transforms/Utils/SCCPSolver.cpp | ||
---|---|---|
1235 | Shouldn't we propagate poison here and in similar cases (by going through the Constant path)? |
llvm/lib/Transforms/Utils/SCCPSolver.cpp | ||
---|---|---|
1235 | Yes. But currently SCCPSolver::getConstant(ValueLatticeElement) doesn't support get undef or poison constant values. And undef or poison are represented in SCCPSolver just by the enum tags which don't have the type information to construct UndefValue or PoisonValue. To support this, we should record the undef or poison in ConstVal instead of just representing it by tags. |
llvm/lib/Transforms/Utils/SCCPSolver.cpp | ||
---|---|---|
1235 | Since recently getConstant() also takes the type, so you can materialize a PoisonValue with the correct type there. |
Shouldn't we propagate poison here and in similar cases (by going through the Constant path)?