Skip to content

[AMDGPU] Handle CreateBinOp not returning BinaryOperator #137791

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

Merged

Conversation

anjenner
Copy link
Contributor

AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls Builder.CreateBinOp() and casts the resulting Value as a BinaryOperator without checking, leading to an assert failure in a case found by fuzzing. In this case, the operands are constant and CreateBinOp does constant folding so returns a Constant instead of a BinaryOperator.

AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls Builder.CreateBinOp()
and casts the resulting Value as a BinaryOperator without checking, leading
to an assert failure in a case found by fuzzing. In this case, the operands
are constant and CreateBinOp does constant folding so returns a Constant
instead of a BinaryOperator.
@llvmbot
Copy link
Member

llvmbot commented Apr 29, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: None (anjenner)

Changes

AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls Builder.CreateBinOp() and casts the resulting Value as a BinaryOperator without checking, leading to an assert failure in a case found by fuzzing. In this case, the operands are constant and CreateBinOp does constant folding so returns a Constant instead of a BinaryOperator.


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

2 Files Affected:

  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp (+4-1)
  • (added) llvm/test/CodeGen/AMDGPU/print-pipeline-passes.AFLCustomIRMutator.ll (+11)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
index 6617373f89c8b..53bea99a2e98c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
@@ -1685,7 +1685,10 @@ bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &I) {
             // return the new value. Just insert a scalar copy and defer
             // expanding it.
             NewElt = Builder.CreateBinOp(Opc, NumEltN, DenEltN);
-            Div64ToExpand.push_back(cast<BinaryOperator>(NewElt));
+            // CreateBinOp does constant folding. If the operands are constant,
+            // it will return a Constant instead of a BinaryOperator.
+            if (auto *NewEltBO = dyn_cast<BinaryOperator>(NewElt))
+              Div64ToExpand.push_back(NewEltBO);
           }
         }
 
diff --git a/llvm/test/CodeGen/AMDGPU/print-pipeline-passes.AFLCustomIRMutator.ll b/llvm/test/CodeGen/AMDGPU/print-pipeline-passes.AFLCustomIRMutator.ll
new file mode 100644
index 0000000000000..583ef3a8bb7c7
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/print-pipeline-passes.AFLCustomIRMutator.ll
@@ -0,0 +1,11 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -O1 < %s | FileCheck -check-prefix=GCN %s
+
+define amdgpu_kernel void @kernel() {
+; GCN-LABEL: kernel:
+; GCN:       ; %bb.0: ; %entry
+; GCN-NEXT:    s_endpgm
+entry:
+  %B = srem <32 x i64> zeroinitializer, zeroinitializer
+  ret void
+}

@anjenner
Copy link
Contributor Author

I'm not totally sure that this is the correct way to fix this, but it seems to pass the tests. I thought I'd ask if it was the right fix in the form of a PR.

@@ -0,0 +1,11 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -O1 < %s | FileCheck -check-prefix=GCN %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test file name doesn't make sense, can you add this case to one of the existing div-rem IR expansion tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't, because this test only works at -O1 and none of the existing div-rem IR expansion tests use that optimisation level. I've renamed the test to srem_zero_zero.ll.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but if you run the pass in isolation it should work?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just move it to amdgpu-codegenprepare-idiv.ll

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works - thanks.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should move test, and can rename and drop amdgpu_kernel

Comment on lines 10098 to 10105
define void @srem_zero_zero() {
; GCN-LABEL: kernel:
; GCN: ; %bb.0: ; %entry
; GCN-NEXT: s_endpgm
entry:
%B = srem <32 x i64> zeroinitializer, zeroinitializer
ret void
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to make this not-dead code and use return value. Also can shrink this to a reasonable vector size, like 2 x

@arsenm arsenm merged commit a36cb01 into llvm:main May 29, 2025
11 checks passed
svkeerthy pushed a commit that referenced this pull request May 29, 2025
AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls
Builder.CreateBinOp() and casts the resulting Value as a BinaryOperator
without checking, leading to an assert failure in a case found by
fuzzing. In this case, the operands are constant and CreateBinOp does
constant folding so returns a Constant instead of a BinaryOperator.
google-yfyang pushed a commit to google-yfyang/llvm-project that referenced this pull request May 29, 2025
AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls
Builder.CreateBinOp() and casts the resulting Value as a BinaryOperator
without checking, leading to an assert failure in a case found by
fuzzing. In this case, the operands are constant and CreateBinOp does
constant folding so returns a Constant instead of a BinaryOperator.
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
AMDGPUCodeGenPrepareImpl::visitBinaryOperator() calls
Builder.CreateBinOp() and casts the resulting Value as a BinaryOperator
without checking, leading to an assert failure in a case found by
fuzzing. In this case, the operands are constant and CreateBinOp does
constant folding so returns a Constant instead of a BinaryOperator.
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.

3 participants