The next generation architectures are expected to accommodate multiple processors on the same chip. While this makes inter-processor communication less costly (as compared to traditional high-end parallel machines), it also makes it even more critical to cut down the number of off- chip memory accesses. Frequent off-chip accesses do not only increase execution cycles but also increase overall power consumption. One way of alleviating this power problem is to divide the off-chip memory into multiple banks, each of which can be power-controlled independently using low-power operating modes. In this work, we focus on a multiprocessor-system-on-a-chip (MPSoC) architecture with a banked memory system, and show how code and data optimizations can help us reduce memory energy consumption. This is achieved by ensuring bank locality, which means that each processor localizes its accesses into a small set of banks. We present a mathematical formulation of the bank locality problem. Our formulation is based on constructing a set of matrix equations that capture the mappings between the data, computation, processor, and memory bank spaces. Based on this formulation, we propose a heuristic solution to the bank locality problem for different scenarios. Our solution involves an iterative process through which we try to satisfy as many matrix constraints as possible. Finally, we report extensive experimental results showing the effectiveness of our strategy in practice. Our results show that the proposed solution improves bank locality significantly, and reduces the overall memory system energy consumption by up to 34% over a strategy that makes use of the low-power modes but does not employ our strategy.