In this case I have the option to discard the fragment in the fragment shader or draw it with a black color. Discarding obviously needs branching, so now I am not sure which option is faster. Generally I assume avoiding branching in shaders is the way to go, but does that hold true for discarding, especially if the branch contains only one call (the discard one)? Or is there no rule of thumb for this case at all and just benchmarking is the way to go?
You can use a stencil instead, This allows the gpu to do an early out test before the fragment shader even starts.
You only have to build the stencil once (possibly with a discard in a simple shader) and you can reuse the stencil in future draws.