-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[SelectionDAG] Fix assertion failure on inline asm register type mismatch #166615
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
Conversation
|
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-llvm-selectiondag Author: Ahmed Nour (ahmednoursphinx) ChangesResolves #166057 Full diff: https://github.com/llvm/llvm-project/pull/166615.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fa0c899dfcc27..9a6a76f73f8fe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -365,7 +365,17 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
NumParts = NumRegs; // Silence a compiler warning.
- assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+
+ // Check if the register type matches the part type
+ if (RegisterVT != PartVT) {
+ diagnosePossiblyInvalidConstraint(
+ *DAG.getContext(), V,
+ "register type (" + EVT(RegisterVT).getEVTString() +
+ ") doesn't match operand type (" + EVT(PartVT).getEVTString() +
+ ")");
+ return DAG.getUNDEF(ValueVT);
+ }
+
assert(RegisterVT.getSizeInBits() ==
Parts[0].getSimpleValueType().getSizeInBits() &&
"Part type sizes don't match!");
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6edf0185df813..bf432f1d56d4a 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -61825,6 +61825,8 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
break;
case 'y': // MMX_REGS if MMX allowed.
if (!Subtarget.hasMMX()) break;
+ // MMX registers are 64-bit only
+ if (VT.getSizeInBits() != 64) break;
return std::make_pair(0U, &X86::VR64RegClass);
case 'v':
case 'x': // SSE_REGS if SSE1 allowed or AVX_REGS if AVX allowed
diff --git a/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll b/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll
new file mode 100644
index 0000000000000..9f4ed28a4d312
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll
@@ -0,0 +1,20 @@
+; RUN: not llc -mtriple=x86_64-unknown-linux-gnu < %s 2>&1 | FileCheck %s
+
+; Test that using MMX register constraint 'y' (64-bit) with a 256-bit vector
+; produces a proper error message instead of an assertion failure.
+
+; CHECK: error: couldn't allocate output register for constraint 'y'
+
+define <8 x i32> @test_mmx_constraint_size_mismatch() {
+entry:
+ %out = tail call <8 x i32> asm "something $0", "=y"()
+ ret <8 x i32> %out
+}
+
+; Also test with a different vector size
+define <4 x i32> @test_mmx_constraint_128bit() {
+entry:
+ %out = tail call <4 x i32> asm "something $0", "=y"()
+ ret <4 x i32> %out
+}
+
|
|
@llvm/pr-subscribers-backend-x86 Author: Ahmed Nour (ahmednoursphinx) ChangesResolves #166057 Full diff: https://github.com/llvm/llvm-project/pull/166615.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fa0c899dfcc27..9a6a76f73f8fe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -365,7 +365,17 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
NumParts = NumRegs; // Silence a compiler warning.
- assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+
+ // Check if the register type matches the part type
+ if (RegisterVT != PartVT) {
+ diagnosePossiblyInvalidConstraint(
+ *DAG.getContext(), V,
+ "register type (" + EVT(RegisterVT).getEVTString() +
+ ") doesn't match operand type (" + EVT(PartVT).getEVTString() +
+ ")");
+ return DAG.getUNDEF(ValueVT);
+ }
+
assert(RegisterVT.getSizeInBits() ==
Parts[0].getSimpleValueType().getSizeInBits() &&
"Part type sizes don't match!");
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6edf0185df813..bf432f1d56d4a 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -61825,6 +61825,8 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
break;
case 'y': // MMX_REGS if MMX allowed.
if (!Subtarget.hasMMX()) break;
+ // MMX registers are 64-bit only
+ if (VT.getSizeInBits() != 64) break;
return std::make_pair(0U, &X86::VR64RegClass);
case 'v':
case 'x': // SSE_REGS if SSE1 allowed or AVX_REGS if AVX allowed
diff --git a/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll b/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll
new file mode 100644
index 0000000000000..9f4ed28a4d312
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll
@@ -0,0 +1,20 @@
+; RUN: not llc -mtriple=x86_64-unknown-linux-gnu < %s 2>&1 | FileCheck %s
+
+; Test that using MMX register constraint 'y' (64-bit) with a 256-bit vector
+; produces a proper error message instead of an assertion failure.
+
+; CHECK: error: couldn't allocate output register for constraint 'y'
+
+define <8 x i32> @test_mmx_constraint_size_mismatch() {
+entry:
+ %out = tail call <8 x i32> asm "something $0", "=y"()
+ ret <8 x i32> %out
+}
+
+; Also test with a different vector size
+define <4 x i32> @test_mmx_constraint_128bit() {
+entry:
+ %out = tail call <4 x i32> asm "something $0", "=y"()
+ ret <4 x i32> %out
+}
+
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
| ; Test that using MMX register constraint 'y' (64-bit) with a 256-bit vector | ||
| ; produces a proper error message instead of an assertion failure. | ||
|
|
||
| ; CHECK: error: couldn't allocate output register for constraint 'y' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the tested error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be the best way to test the specific diagnostic path? The register
allocator's validation runs before getCopyFromPartsVector, so the specific message
from the fix is only reached if earlier checks are bypassed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No? The register allocation is very far removed and much later than the DAG construction where getCopyFromPartsVector is used
| } | ||
|
|
||
| ; Also test with a different vector size | ||
| define <4 x i32> @test_mmx_constraint_128bit() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check errors in each instance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please elaborate more about the instances we need to test? Currently we have two test cases covering different vector size mismatches: a 256-bit vector (<8 x i32>) and a 128-bit vector (<4 x i32>), both using the MMX 'y' constraint which expects 64-bit operands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each of these cases will emit an error, check all errors that are in stderr
|
This is not what I expected. We should do the check as early as in the front end. I assume we just need to add back in X86AdjustInlineAsmType which was removed in e59a619 |
Thanks @phoebewang i have reverted the frontend check , please check when you have time |
|
Hey @arsenm i have updated the code based on @phoebewang recommendations , please have a look again when you have time |
The size check in X86ISelLowering::getRegForInlineAsmConstraint was too restrictive. MMX registers can legitimately hold 32-bit integers (i32), not just 64-bit vectors. The frontend validation in X86AdjustInlineAsmType is sufficient for catching invalid vector sizes.
|
@phoebewang updated please check when you have time |
Co-authored-by: Phoebe Wang <phoebe.wang@intel.com>
phoebewang
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
|
Hey @RKSimon @phoebewang can you merge this please? |
Resolves #166057