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

[Inliner] Check number of operands in AddReturnAttributes #87093

Closed

Conversation

erthalion
Copy link
Contributor

@erthalion erthalion commented Mar 29, 2024

The commit 2da4960 enabled noundef attributes propagation. It looks like ret void is considered to be noundef, thus ValidUB.hasAttributes now returns true for this type of instructions and everything proceed further to work with operands. The issue is that such instruction doesn't have operands, which means when accessing RI->getOperand(0) inliner pass crashes with an assert:

llvm/include/llvm/IR/Instructions.h:3420: llvm::Value* llvm::ReturnInst::getOperand(unsigned int) const:
Assertion `i_nocapture < OperandTraits<ReturnInst>::operands(this) && "getOperand() out of range!"' failed.

Fix that by verifying if the ReturnInst in fact has some operands to process.

/cc @goldsteinn as an author of the commit referenced in [3], and @chandlerc as mentioned in code_owners regarding inlining pass.

Fixes #86162

The commit 2da4960 enabled `noundef` attributes propagation. It looks
like ret void is considered to be `noundef` thus `ValidUB.hasAttributes`
now returns true for this type of instructions and everything proceed
further to work with operands. The issue is that such instruction
doesn't have operands, which means when accessing `RI->getOperand(0)`
inliner pass crashes with an assert:

    llvm/include/llvm/IR/Instructions.h:3420: llvm::Value* llvm::ReturnInst::getOperand(unsigned int) const:
    Assertion `i_nocapture < OperandTraits<ReturnInst>::operands(this) && "getOperand() out of range!"' failed.

Fix that by verifying if the ReturnInst in fact has some operands to
process.

Fixes llvm#86163
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 29, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Dmitrii Dolgov (erthalion)

Changes

The commit 2da4960 enabled noundef attributes propagation. It looks like ret void is considered to be noundef, thus ValidUB.hasAttributes now returns true for this type of instructions and everything proceed further to work with operands. The issue is that such instruction doesn't have operands, which means when accessing RI-&gt;getOperand(0) inliner pass crashes with an assert:

llvm/include/llvm/IR/Instructions.h:3420: llvm::Value* llvm::ReturnInst::getOperand(unsigned int) const:
Assertion `i_nocapture &lt; OperandTraits&lt;ReturnInst&gt;::operands(this) &amp;&amp; "getOperand() out of range!"' failed.

Fix that by verifying if the ReturnInst in fact has some operands to process.

/cc @goldsteinn as an author of the commit referenced in [3], and @chandlerc as mentioned in code_owners regarding inlining pass.

Fixes #86162


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

1 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/InlineFunction.cpp (+1-1)
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 833dcbec228b88..d5cf6bd036e07c 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1384,7 +1384,7 @@ static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) {
 
   for (auto &BB : *CalledFunction) {
     auto *RI = dyn_cast<ReturnInst>(BB.getTerminator());
-    if (!RI || !isa<CallBase>(RI->getOperand(0)))
+    if (!RI || RI->getNumOperands() == 0 || !isa<CallBase>(RI->getOperand(0)))
       continue;
     auto *RetVal = cast<CallBase>(RI->getOperand(0));
     // Check that the cloned RetVal exists and is a call, otherwise we cannot

@aeubanks
Copy link
Contributor

aeubanks commented Apr 4, 2024

could you add a test so it's clearer what the input IR causing the crash is? or at least just paste some reduced IR that crashes with opt -passes=inline (can reduce with llvm-reduce)

it'd seem like noundef on a function that returns void shouldn't be valid

@aeubanks
Copy link
Contributor

aeubanks commented Apr 4, 2024

yeah that's not allowed (https://godbolt.org/z/ffM1qnfrn) so I'm not sure exactly what you're seeing. perhaps the input IR is already broken (run it through the verifier with opt -passes=verify to check)

@erthalion
Copy link
Contributor Author

yeah that's not allowed (https://godbolt.org/z/ffM1qnfrn) so I'm not sure exactly what you're seeing. perhaps the input IR is already broken (run it through the verifier with opt -passes=verify to check)

Interesting, let me verify the IR.

@erthalion
Copy link
Contributor Author

With help from @macdice we most likely found the reason behind #86162. PostgreSQL generates the module passed to the inliner, and it turns out one part of the generator copies function attributes, eventually applying noudef where it shouldn't be applied. Adding verify pass shows it early on, thanks for the advice!

Unless you folks think that the extra check proposed in this PR makes sense as a general defense measure, I'm going to close the PR and the issue.

@erthalion erthalion closed this Apr 8, 2024
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.

[inliner][bug] AddReturnAttributes crash with non existing operands
3 participants