Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DivRemPairs] Do not freeze poisons that can't be undef #92627

Merged
merged 1 commit into from
May 20, 2024

Conversation

krzysz00
Copy link
Contributor

@krzysz00 krzysz00 commented May 18, 2024

Per comments in DivRemPairs, the rewrite from

    %div = div %X, %Y
    %rem = rem %X, %Y

to

    %div = div %X, %Y
    %.mul = mul %div, %Y
    %rem = sub %X, %mul

is unsound when %X or %Y are undef.

However, it is known to be sound if %X or %Y are poison but can't be undef, since both the pre- and post-rewrite %rem are poison.

Additionally, proofs: https://alive2.llvm.org/ce/z/xtNQ8j

A comment in the pass listed a TODO for changing a usage of isGuaranteedNotToBeUndefOrPoison() in the pass to something that only detects undef. Such a function has been implemented since the time that TODO was written, but has not been used.

Therefore, this commit updates DivRemPairs to use
isGuaranteedNotToBeUndef() instead.

@llvmbot
Copy link
Collaborator

llvmbot commented May 18, 2024

@llvm/pr-subscribers-backend-amdgpu

@llvm/pr-subscribers-llvm-transforms

Author: Krzysztof Drewniak (krzysz00)

Changes

Per comments in DivRemPairs, the rewrite from

    %div = div %X, %Y
    %rem = rem %X, %Y

to

    %div = div %X, %Y
    %.mul = mul %div, %Y
    %rem = sub %X, %mul

is unsound when %X or %Y are undef.

However, it is known to be sound if %X or %Y are poison but can't be undef, since both the pre- and post-rewrite %rem are poison.

A comment in the pass listed a TODO for changing a usage of isGuaranteedNotToBeUndefOrPoison() in the pass to something that only detects undef. Such a function has been implemented since the time that TODO was written, but has not been used.

Therefore, this commit updates DivRemPairs to use
isGuaranteedNotToBeUndef() instead.


Full diff: https://github.com/llvm/llvm-project/pull/92627.diff

1 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/DivRemPairs.cpp (+2-3)
diff --git a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp
index 45f36a36b5dd0..f7ada9fb8eb8a 100644
--- a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp
+++ b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp
@@ -381,8 +381,7 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
       //   %mul = mul %div, 1   // %mul = undef
       //   %rem = sub %x, %mul  // %rem = undef - undef = undef
       // If X is not frozen, %rem becomes undef after transformation.
-      // TODO: We need a undef-specific checking function in ValueTracking
-      if (!isGuaranteedNotToBeUndefOrPoison(X, nullptr, DivInst, &DT)) {
+      if (!isGuaranteedNotToBeUndef(X, nullptr, DivInst, &DT)) {
         auto *FrX =
             new FreezeInst(X, X->getName() + ".frozen", DivInst->getIterator());
         DivInst->setOperand(0, FrX);
@@ -390,7 +389,7 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
       }
       // Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0,
       // but %rem in tgt can be one of many integer values.
-      if (!isGuaranteedNotToBeUndefOrPoison(Y, nullptr, DivInst, &DT)) {
+      if (!isGuaranteedNotToBeUndef(Y, nullptr, DivInst, &DT)) {
         auto *FrY =
             new FreezeInst(Y, Y->getName() + ".frozen", DivInst->getIterator());
         DivInst->setOperand(1, FrY);

krzysz00 added a commit to krzysz00/llvm-project that referenced this pull request May 18, 2024
The tests are added to a new AMDGPU/ subdirectory since I found the
missed optimization while hacking on AMDGPU code. Also, this ensures
that AMDGPU, which uses DivRemPass, is being checked for existing
expected behavior.
@dtcxzyw dtcxzyw requested review from arsenm and nikic May 18, 2024 02:28
krzysz00 added a commit that referenced this pull request May 20, 2024
The tests are added to a new AMDGPU/ subdirectory since I found the
missed optimization while hacking on AMDGPU code. Also, this ensures
that AMDGPU, which uses DivRemPass, is being checked for existing
expected behavior.
Per comments in DivRemPairs, the rewrite from
```llvm
    %div = div %X, %Y
    %rem = rem %X, %Y
```
to
```llvm
    %div = div %X, %Y
    %.mul = mul %div, %Y
    %rem = sub %X, %mul
```
is unsound when %X or %Y are undef.

However, it is known to be sound if %X or %Y are poison but can't be
undef, since both the pre- and post-rewrite %rem are `poison`.

Additionally, proofs: https://alive2.llvm.org/ce/z/xtNQ8j

A comment in the pass listed a TODO for changing a usage of
isGuaranteedNotToBeUndefOrPoison() in the pass to something that only
detects undef. Such a function has been implemented since the time
that TODO was written, but has not been used.

Therefore, this commit updates DivRemPairs to use
isGuaranteedNotToBeUndef() instead.
@krzysz00 krzysz00 merged commit 8b22bb8 into llvm:main May 20, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants