You can "hoist" bounds checks out of the loop by using slices, as long as LLVM can follow that the slice len and index variable are related:
let len = vec.len();
let slice = &vec[0..len];
for i in 0..len {
slice[i] // no bounds check
}
And unsafe {get_unchecked()} is fine. You can (with care) build a safe matrix multiplication function on top of it, so the risk doesn't spread.