If there are non-load/store users of the promoted pointer, we currently abort promotion. However, having such users isn't really relevant to the transform. We already separately check that a) there are no instructions that modref the promoted pointer and b) that a pointer capture disables store promotion.
In the affected @test_captured_in_loop test case we have a readnone capture of the promoted pointer, which means that load promotion can be performed (while store promotion cannot).
If you're interested, we can be smarter here for some uses. e.g. a argument to a call marked experimental gives us deref facts. (Though that requires guaranteed to execute reasoning - which for some reason we don't use for loads?)