When flattening the loop, if the GEP was inbound, it should stay inbound, because the only thing that changed is how the pointers are calculated, not the elements being accessed. Proof: https://alive2.llvm.org/ce/z/dApMpQ
Now that InstCombine canonicalises add+gep to gep+gep, LoopFlatten needs to recognise (gep (gep ptr (i*M)), j) as being something it can optimise.