Loop-invariant code motion with unsafe operations
This kind of optimization is more difficult than typical data-flow based transformations, because you need to actually change the branching structure of the control flow graph.  

You need something more than SSA (or something more than the dataflow graph you get from reaching definitions.)  That "something" is the control dependence graph (which relies on the same (post)dominator analysis that you use to construct the SSA graph.  (Google for "program dependence graph" (which is the combination of the control-dependence graph and the SSA data-flow graph).)  Loop invariants (including loop invariant conditionals) are "obvious" in the program dependence graph.  A loop invariant is any node all of whose data and control dependences come from outside the loop.

Unfortunately, in the general case, rebuilding a control-flow graph from the program-dependence graph is somewhat involved.  (Google for "percolation scheduling" and "gated SSA form" if you are interested.  Also (self promotion) my dissertation gives a (terse) overview of a method for converting from PDG back to CFG.)  You can, luckily, do something substantially simpler if you are willing to restrict your transformation to specific structured control flow (in your case, an if-else block inside a do-while block.)  This is the same simplification that loop unswitching makes.

So working through the steps.  First convert while and for loops to if-do-while

read a
read_array bs
b = bs.first
if (b is not bs.end):
  do:
    if (a != 0):
      c = 5 / a
      print b * c
    more stuff
    b = b.next
  while (b is not bs.end)


Then (as with loop unswitching) you see that a != 0 is loop invariant, so the if statement is loop invariant, so any statements inside the if block that are loop invariant (c = 5/a) can be moved out of the loop (along with the conditional that protects those statements.)  Essentially what you are doing is breaking each invariant conditional block into the parts that are and are not loop invariant:

read a
read_array bs
b = bs.first
if (b is not bs.end):
  do:
    if (a != 0):
      c = 5 / a
    if (a != 0):
      print b * c
    more stuff
    b = b.next
  while (b is not bs.end)


Then you can move the entirety of the blocks that are completely loop-invariant out of the loop:

read a
read_array bs
b = bs.first
if (b is not bs.end):
  if (a != 0):
    c = 5 / a
  do:
    if (a != 0):
      print b * c
    more stuff
    b = b.next
  while (b is not bs.end)