This PR pulls the upstream change, Reassociate: add global reassociation algorithm (llvm/llvm-project@b8a330c), into DXC.
For the code below:
foo = (a * b) * c
bar = (a * d) * c
As the upstream change states, it can recognize the a*c is a common factor and redundant.
However, this upstream change might overlook some obvious common factors. One case has been observed is:
%2 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)
%3 = extractvalue %dx.types.CBufRet.f32 %2, 3
%4 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)
%5 = extractvalue %dx.types.CBufRet.f32 %4, 1
%6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)
%7 = extractvalue %dx.types.CBufRet.f32 %6, 3
%8 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)
%9 = extractvalue %dx.types.CBufRet.f32 %8, 1
%11 = fmul fast float %3, %10
%12 = fmul fast float %11, %5
%14 = fmul fast float %7, %13
%15 = fmul fast float %14, %9 ---> %3*%5 == %7*%9 --> they should be reassociated to a common factor
The upstream change can't identify this common factor because DXC don't know (%3, %7) and (%7, %9) are redundant when running Reassociate pass. The redundancy of (%3, %7) and (%7, %9) will be eliminated after GVN pass.
For DXC can identify more common factors, this PR will aggressively run Reassociate pass again after GVN pass and it will run GVN pass after it to remove the redundancy generared in the second run of Reassociate pass.
One issue of this PR is changing the order of floating point operations will cause the precision issue and very different result of some edge cases.
So this PR adds the disable-aggressive-reassociation flag (it's false by default) to the non-upstream change. It can be used to mitigate and debug the issue caused by this PR.
Fixes #6593.