https://github.com/ahmednoursphinx updated https://github.com/llvm/llvm-project/pull/166615
>From 684e005c76d7db5500fb0925547b58327c993d84 Mon Sep 17 00:00:00 2001 From: ahmed <[email protected]> Date: Wed, 5 Nov 2025 20:52:13 +0200 Subject: [PATCH 1/4] [SelectionDAG] Fix assertion failure on inline asm register type mismatch --- .../SelectionDAG/SelectionDAGBuilder.cpp | 12 ++++++++++- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 ++ .../inline-asm-y-constraint-size-mismatch.ll | 20 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll 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 +} + >From 36a7461181238819e0775958493cff4305e235de Mon Sep 17 00:00:00 2001 From: ahmed <[email protected]> Date: Wed, 5 Nov 2025 20:54:34 +0200 Subject: [PATCH 2/4] chore: Fix formatting --- .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 14 +++++++------- llvm/lib/Target/X86/X86ISelLowering.cpp | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 9a6a76f73f8fe..ecdc3750e6e02 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -365,17 +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. - + // 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() + - ")"); + 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 bf432f1d56d4a..2a02f12b18181 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -61826,7 +61826,8 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, case 'y': // MMX_REGS if MMX allowed. if (!Subtarget.hasMMX()) break; // MMX registers are 64-bit only - if (VT.getSizeInBits() != 64) break; + 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 >From e81a714c1ed5425885048dd54e0382ff6c6051c0 Mon Sep 17 00:00:00 2001 From: ahmed <[email protected]> Date: Thu, 6 Nov 2025 08:00:18 +0200 Subject: [PATCH 3/4] PR Feedback --- .../SelectionDAG/SelectionDAGBuilder.cpp | 2 +- .../inline-asm-y-constraint-size-mismatch.ll | 22 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index ecdc3750e6e02..9432d42265242 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -373,7 +373,7 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL, EVT(RegisterVT).getEVTString() + ") doesn't match operand type (" + EVT(PartVT).getEVTString() + ")"); - return DAG.getUNDEF(ValueVT); + return DAG.getPOISON(ValueVT); } assert(RegisterVT.getSizeInBits() == 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 index 9f4ed28a4d312..817ecacadaa1a 100644 --- a/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll +++ b/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll @@ -1,18 +1,26 @@ -; RUN: not llc -mtriple=x86_64-unknown-linux-gnu < %s 2>&1 | FileCheck %s +; RUN: not llc -mtriple=x86_64-unknown-linux-gnu -filetype=null %s 2>&1 | FileCheck -implicit-check-not=error %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. +; Test that using MMX register constraint 'y' (64-bit) with mismatched vector sizes +; produces an error message instead of an assertion failure. +; +; This is a regression test for an assertion that would fire in getCopyFromPartsVector: +; Assertion `RegisterVT == PartVT && "Part type doesn't match vector breakdown!"' failed +; +; The error can be caught at different stages: +; - During register allocation: "couldn't allocate output register for constraint" +; - In getCopyFromPartsVector: "register type (X) doesn't match operand type (Y)" +; +; We test multiple invalid vector sizes to ensure the fix handles various mismatches. -; CHECK: error: couldn't allocate output register for constraint 'y' - -define <8 x i32> @test_mmx_constraint_size_mismatch() { +define <8 x i32> @test_mmx_constraint_256bit() { +; CHECK: error: {{couldn't allocate output register for constraint 'y'|register type .* doesn't match operand type}} 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() { +; CHECK: error: {{couldn't allocate output register for constraint 'y'|register type .* doesn't match operand type}} entry: %out = tail call <4 x i32> asm "something $0", "=y"() ret <4 x i32> %out >From 91650a4d65eb2ffe9a403f439c4f4709998a1009 Mon Sep 17 00:00:00 2001 From: ahmed <[email protected]> Date: Thu, 6 Nov 2025 11:57:25 +0200 Subject: [PATCH 4/4] Revert to frontend check --- clang/lib/CodeGen/Targets/X86.cpp | 11 ++++++++ clang/test/CodeGen/X86/mmx-inline-asm-error.c | 18 ++++++++++++ .../SelectionDAG/SelectionDAGBuilder.cpp | 12 +------- .../inline-asm-y-constraint-size-mismatch.ll | 28 ------------------- 4 files changed, 30 insertions(+), 39 deletions(-) delete mode 100644 llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 8daf8eb1d39f1..5aac49237aabd 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -27,6 +27,17 @@ bool IsX86_MMXType(llvm::Type *IRType) { static llvm::Type *X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, StringRef Constraint, llvm::Type *Ty) { + bool IsMMXCons = llvm::StringSwitch<bool>(Constraint) + .Cases("y", "&y", "^Ym", true) + .Default(false); + if (IsMMXCons && Ty->isVectorTy()) { + if (cast<llvm::VectorType>(Ty)->getPrimitiveSizeInBits().getFixedValue() != + 64) { + // Invalid MMX constraint + return nullptr; + } + } + if (Constraint == "k") { llvm::Type *Int1Ty = llvm::Type::getInt1Ty(CGF.getLLVMContext()); return llvm::FixedVectorType::get(Int1Ty, Ty->getScalarSizeInBits()); diff --git a/clang/test/CodeGen/X86/mmx-inline-asm-error.c b/clang/test/CodeGen/X86/mmx-inline-asm-error.c index 1e2246176a117..1bf48b83d3ae6 100644 --- a/clang/test/CodeGen/X86/mmx-inline-asm-error.c +++ b/clang/test/CodeGen/X86/mmx-inline-asm-error.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only %s + +// Test that MMX register constraint 'y' with mismatched vector sizes +// produces a proper error message instead of an assertion failure. + typedef int vec256 __attribute__((ext_vector_type(8))); vec256 foo(vec256 in) { @@ -11,3 +15,17 @@ vec256 foo(vec256 in) { return out; } +// Additional tests for different vector sizes +typedef int vec128 __attribute__((ext_vector_type(4))); +typedef int vec64 __attribute__((ext_vector_type(2))); + +void test_128bit_mismatch() { + vec128 out; + __asm__("nop" : "=y"(out)); // expected-error {{invalid output size for constraint '=y'}} +} + +void test_64bit_valid() { + // This should work - 64-bit vector matches MMX register size + vec64 out; + __asm__("nop" : "=y"(out)); +} diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 9432d42265242..fa0c899dfcc27 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -365,17 +365,7 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL, assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); NumParts = NumRegs; // Silence a compiler warning. - - // 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.getPOISON(ValueVT); - } - + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); assert(RegisterVT.getSizeInBits() == Parts[0].getSimpleValueType().getSizeInBits() && "Part type sizes don't match!"); 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 deleted file mode 100644 index 817ecacadaa1a..0000000000000 --- a/llvm/test/CodeGen/X86/inline-asm-y-constraint-size-mismatch.ll +++ /dev/null @@ -1,28 +0,0 @@ -; RUN: not llc -mtriple=x86_64-unknown-linux-gnu -filetype=null %s 2>&1 | FileCheck -implicit-check-not=error %s - -; Test that using MMX register constraint 'y' (64-bit) with mismatched vector sizes -; produces an error message instead of an assertion failure. -; -; This is a regression test for an assertion that would fire in getCopyFromPartsVector: -; Assertion `RegisterVT == PartVT && "Part type doesn't match vector breakdown!"' failed -; -; The error can be caught at different stages: -; - During register allocation: "couldn't allocate output register for constraint" -; - In getCopyFromPartsVector: "register type (X) doesn't match operand type (Y)" -; -; We test multiple invalid vector sizes to ensure the fix handles various mismatches. - -define <8 x i32> @test_mmx_constraint_256bit() { -; CHECK: error: {{couldn't allocate output register for constraint 'y'|register type .* doesn't match operand type}} -entry: - %out = tail call <8 x i32> asm "something $0", "=y"() - ret <8 x i32> %out -} - -define <4 x i32> @test_mmx_constraint_128bit() { -; CHECK: error: {{couldn't allocate output register for constraint 'y'|register type .* doesn't match operand type}} -entry: - %out = tail call <4 x i32> asm "something $0", "=y"() - ret <4 x i32> %out -} - _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
