The original implementation will create two intermediate AffineMap in the context, calling this compose function with different values multiple times will occupy a lot of memory. To improve the performance, we can call the AffineExpr::replace directly, so we don't need to store all combinations of values in the context.
Multi-Level Intermediate Representation
See https://mlir.llvm.org/ for more information.