-- | Extract allocations from 'Thread' statements with
-- 'extractThreadAllocations'.
extractKernelBodyAllocations :: Names -> KernelBody InKernel
                             -> Either String (KernelBody InKernel,
                                               M.Map VName (SubExp, Space))
extractKernelBodyAllocations bound_before_body kbody = do
  (allocs, stms) <- mapAccumLM extract M.empty $ kernelBodyStms kbody
  return (kbody { kernelBodyStms = concat stms }, allocs)
  where extract allocs bnd = do
          (bnds, body_allocs) <- extractThreadAllocations bound_before_body [bnd]
          return (allocs <> body_allocs, bnds)
extractKernelBodyAllocations :: Names -> KernelBody InKernel
                             -> Either String (KernelBody InKernel,
                                               M.Map VName (SubExp, Space))
extractKernelBodyAllocations bound_before_body kbody = do
  (allocs, stms) <- mapAccumLM extract M.empty $ kernelBodyStms kbody
  return (kbody { kernelBodyStms = concat stms }, allocs)
  where extract allocs bnd = do
          (bnds, body_allocs) <- extractThreadAllocations bound_before_body [bnd]
          return (allocs <> body_allocs, bnds)
extractKernelBodyAllocations bound_before_body kbody = do
  (allocs, stms) <- mapAccumLM extract M.empty $ kernelBodyStms kbody
  return (kbody { kernelBodyStms = concat stms }, allocs)
  where extract allocs bnd = do
          (bnds, body_allocs) <- extractThreadAllocations bound_before_body [bnd]
          return (allocs <> body_allocs, bnds)