Given a program
x.fr = freeze x c = icmp eq x.fr, y br c, A, B A: use(x) // here
We can replace x with y.
This can be proved by case analysis.
If y is undef or poison, c is also undef or poison, so br c raises UB.
If y is a well-defined value, x.fr and y are equal, so x (which is more undefined than x) can be replaced with y.
Demonstration: https://alive2.llvm.org/ce/z/UWX2fL , https://alive2.llvm.org/ce/z/vxcMLS , https://alive2.llvm.org/ce/z/_mcXgJ
If the branch condition itself was frozen (br freeze (icmp eq x, y)), this optimization isn't valid (https://alive2.llvm.org/ce/z/X5eetc ).
If either x or y is constant, converting it into br (icmp eq (freeze x), y) will make the optimization above fire again.
InstCombine might be a good candidate for doing this preprocessing.