We found that the fold-scf-if transformation may introduce undefined behavior.
Below is an MLIR example demonstrating that the fold-scf-if transformation may introduce undefined behavior. In this example, we have a function @example that selectively stores a float value in memory references %A and %B based on the value of %cond. The function assumes that %A and %B are not initialized within the function.
In the transformed code, the two affine.load operations are executed unconditionally, which may access uninitialized memory. In the original code, the affine.store operations were executed only when the corresponding conditions were met. Specifically, when %cond is true, affine.store %a, %A[0] is executed, and when %cond is false, affine.store %a, %B[0] is executed. In this way, the respective memory locations in %A or %B are initialized before the memory access.
However, in the transformed code, the two affine.load operations are executed regardless of the %arg4 value. This may lead to uninitialized memory access in certain cases, resulting in undefined behavior. Specifically, neither %arg0[0] nor %arg1[0] are initialized before the affine.load operations.
This access to uninitialized memory was not present in the original code, resulting in new undefined behavior in the transformed code. The same issue also appears in the match-store-no-else.mlir and match-store-diff-mem.mlir unit tests.
We found that the fold-scf-if transformation may introduce undefined behavior.
Below is an MLIR example demonstrating that the
fold-scf-if
transformation may introduce undefined behavior. In this example, we have a function@example
that selectively stores a float value in memory references%A
and%B
based on the value of%cond
. The function assumes that%A
and%B
are not initialized within the function.After applying the
fold-scf-if
transformation, we get the following code:In the transformed code, the two
affine.load
operations are executed unconditionally, which may access uninitialized memory. In the original code, theaffine.store
operations were executed only when the corresponding conditions were met. Specifically, when%cond
istrue
,affine.store %a, %A[0]
is executed, and when%cond
isfalse
,affine.store %a, %B[0]
is executed. In this way, the respective memory locations in %A or %B are initialized before the memory access.However, in the transformed code, the two
affine.load
operations are executed regardless of the%arg4
value. This may lead to uninitialized memory access in certain cases, resulting in undefined behavior. Specifically, neither%arg0[0]
nor%arg1[0]
are initialized before theaffine.load
operations.This access to uninitialized memory was not present in the original code, resulting in new undefined behavior in the transformed code. The same issue also appears in the
match-store-no-else.mlir
andmatch-store-diff-mem.mlir
unit tests.