[llvm] [CodeGen] Enhance inline asm constraint diagnostics (PR #101354)
Evgenii Kudriashov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 31 09:04:48 PDT 2024
https://github.com/e-kud created https://github.com/llvm/llvm-project/pull/101354
None
>From 2dce3e99fb63f3d5ba8ae4ffffbcce756e635960 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Wed, 17 Jul 2024 08:36:54 -0700
Subject: [PATCH] [CodeGen] Enhance inline asm constraint diagnostics
---
llvm/include/llvm/CodeGen/TargetLowering.h | 3 +-
.../CodeGen/GlobalISel/InlineAsmLowering.cpp | 3 +-
.../SelectionDAG/FunctionLoweringInfo.cpp | 3 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 56 ++++++++++---------
.../CodeGen/SelectionDAG/TargetLowering.cpp | 11 ++--
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 3 +-
llvm/lib/Target/AMDGPU/SIISelLowering.h | 3 +-
llvm/lib/Target/ARM/ARMISelLowering.h | 3 +-
llvm/lib/Target/AVR/AVRISelLowering.h | 3 +-
llvm/lib/Target/BPF/BPFISelLowering.h | 3 +-
llvm/lib/Target/CSKY/CSKYISelLowering.h | 3 +-
llvm/lib/Target/Hexagon/HexagonISelLowering.h | 3 +-
llvm/lib/Target/Lanai/LanaiISelLowering.h | 3 +-
.../Target/LoongArch/LoongArchISelLowering.h | 3 +-
llvm/lib/Target/M68k/M68kISelLowering.h | 3 +-
llvm/lib/Target/MSP430/MSP430ISelLowering.h | 3 +-
llvm/lib/Target/Mips/MipsISelLowering.h | 3 +-
llvm/lib/Target/NVPTX/NVPTXISelLowering.h | 3 +-
llvm/lib/Target/PowerPC/PPCISelLowering.h | 3 +-
llvm/lib/Target/RISCV/RISCVISelLowering.h | 3 +-
llvm/lib/Target/SPIRV/SPIRVISelLowering.h | 3 +-
llvm/lib/Target/Sparc/SparcISelLowering.h | 3 +-
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 3 +-
llvm/lib/Target/VE/VEISelLowering.h | 3 +-
.../WebAssembly/WebAssemblyISelLowering.h | 3 +-
llvm/lib/Target/X86/X86ISelLowering.cpp | 50 +++++++++++------
llvm/lib/Target/X86/X86ISelLowering.h | 3 +-
llvm/lib/Target/XCore/XCoreISelLowering.h | 3 +-
.../X86/asm-reject-reg-type-mismatch-avx.ll | 2 +-
.../X86/asm-reject-reg-type-mismatch.ll | 6 +-
llvm/test/CodeGen/X86/asm-reject-rex.ll | 6 +-
llvm/test/CodeGen/X86/asm-reject-vk32-vk64.ll | 8 +--
llvm/test/CodeGen/X86/asm-reject-x87-int.ll | 2 +-
llvm/test/CodeGen/X86/asm-reject-xmm16.ll | 7 ++-
.../X86/inline-asm-avx512f-x-constraint.ll | 4 +-
llvm/test/CodeGen/X86/inline-asm-x-i128.ll | 2 +-
llvm/test/CodeGen/X86/pr37359.ll | 2 +-
llvm/test/CodeGen/X86/pr50907.ll | 2 +-
38 files changed, 142 insertions(+), 91 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 9d9886f4920a2..7e0f7a269ed59 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5034,7 +5034,8 @@ class TargetLowering : public TargetLoweringBase {
/// returns a register number of 0 and a null register class pointer.
virtual std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const;
virtual InlineAsm::ConstraintCode
getInlineAsmMemConstraint(StringRef ConstraintCode) const {
diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
index 81f25b21a0409..20c6713c17b0d 100644
--- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
@@ -93,8 +93,9 @@ static void getRegistersForValue(MachineFunction &MF,
// register class, find it.
Register AssignedReg;
const TargetRegisterClass *RC;
+ std::string ErrMsg;
std::tie(AssignedReg, RC) = TLI.getRegForInlineAsmConstraint(
- &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
+ &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT, ErrMsg);
// RC is unset only on failure. Return immediately.
if (!RC)
return;
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 8f5b05b662b33..0bb7fe438ad8e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -192,9 +192,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
if (Op.Type == InlineAsm::isClobber) {
// Clobbers don't have SDValue operands, hence SDValue().
TLI->ComputeConstraintToUse(Op, SDValue(), DAG);
+ std::string ErrMsg;
std::pair<unsigned, const TargetRegisterClass *> PhysReg =
TLI->getRegForInlineAsmConstraint(TRI, Op.ConstraintCode,
- Op.ConstraintVT);
+ Op.ConstraintVT, ErrMsg);
if (PhysReg.first == SP)
MF->getFrameInfo().setHasOpaqueSPAdjustment(true);
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 9f5e6466309e9..a22fb64cdf94f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9516,13 +9516,14 @@ static void patchMatchingInput(const SDISelAsmOperandInfo &OpInfo,
const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo();
const auto &TLI = DAG.getTargetLoweringInfo();
+ std::string ErrMsg;
std::pair<unsigned, const TargetRegisterClass *> MatchRC =
TLI.getRegForInlineAsmConstraint(TRI, OpInfo.ConstraintCode,
- OpInfo.ConstraintVT);
+ OpInfo.ConstraintVT, ErrMsg);
std::pair<unsigned, const TargetRegisterClass *> InputRC =
TLI.getRegForInlineAsmConstraint(TRI, MatchingOpInfo.ConstraintCode,
- MatchingOpInfo.ConstraintVT);
+ MatchingOpInfo.ConstraintVT, ErrMsg);
if ((OpInfo.ConstraintVT.isInteger() !=
MatchingOpInfo.ConstraintVT.isInteger()) ||
(MatchRC.second != InputRC.second)) {
@@ -9588,7 +9589,7 @@ static SDValue getAddressForMemoryInput(SDValue Chain, const SDLoc &Location,
///
/// OpInfo describes the operand
/// RefOpInfo describes the matching operand if any, the operand otherwise
-static std::optional<unsigned>
+static std::optional<std::string>
getRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
SDISelAsmOperandInfo &OpInfo,
SDISelAsmOperandInfo &RefOpInfo) {
@@ -9608,11 +9609,12 @@ getRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
// register class, find it.
unsigned AssignedReg;
const TargetRegisterClass *RC;
+ std::string ErrMsg;
std::tie(AssignedReg, RC) = TLI.getRegForInlineAsmConstraint(
- &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
+ &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT, ErrMsg);
// RC is unset only on failure. Return immediately.
if (!RC)
- return std::nullopt;
+ return ErrMsg;
// Get the actual register value type. This is important, because the user
// may have asked for (e.g.) the AX register in i32 type. We need to
@@ -9684,7 +9686,9 @@ getRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
if (I == RC->end()) {
// RC does not contain the selected register, which indicates a
// mismatch between the register and the required type/bitwidth.
- return {AssignedReg};
+ return "register '" + std::string(TRI.getName(AssignedReg)) +
+ "' allocated for constraint '" + OpInfo.ConstraintCode +
+ "' does not match required type " + ValueVT.getEVTString();
}
}
@@ -9933,18 +9937,6 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
OpInfo.isMatchingInputConstraint()
? ConstraintOperands[OpInfo.getMatchedOperand()]
: OpInfo;
- const auto RegError =
- getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
- if (RegError) {
- const MachineFunction &MF = DAG.getMachineFunction();
- const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
- const char *RegName = TRI.getName(*RegError);
- emitInlineAsmError(Call, "register '" + Twine(RegName) +
- "' allocated for constraint '" +
- Twine(OpInfo.ConstraintCode) +
- "' does not match required type");
- return;
- }
auto DetectWriteToReservedRegister = [&]() {
const MachineFunction &MF = DAG.getMachineFunction();
@@ -9983,12 +9975,17 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Otherwise, this outputs to a register (directly for C_Register /
// C_RegisterClass, and a target-defined fashion for
// C_Immediate/C_Other). Find a register that we can use.
- if (OpInfo.AssignedRegs.Regs.empty()) {
+ const auto RegError =
+ getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+ if (RegError) {
emitInlineAsmError(
Call, "couldn't allocate output register for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
+ Twine(OpInfo.ConstraintCode) +
+ (RegError->empty() ? "'" : ("': " + Twine(*RegError))));
return;
}
+ assert(!OpInfo.AssignedRegs.Regs.empty() &&
+ "register must be allocated or an error emitted");
if (DetectWriteToReservedRegister())
return;
@@ -10157,13 +10154,17 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
return;
}
- // Copy the input into the appropriate registers.
- if (OpInfo.AssignedRegs.Regs.empty()) {
- emitInlineAsmError(Call,
- "couldn't allocate input reg for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
+ const auto RegError =
+ getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+ if (RegError) {
+ emitInlineAsmError(
+ Call, "couldn't allocate input reg for constraint '" +
+ Twine(OpInfo.ConstraintCode) +
+ (RegError->empty() ? "'" : ("': " + Twine(*RegError))));
return;
}
+ assert(!OpInfo.AssignedRegs.Regs.empty() &&
+ "register must be allocated or an error emitted");
if (DetectWriteToReservedRegister())
return;
@@ -10177,15 +10178,18 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
0, dl, DAG, AsmNodeOperands);
break;
}
- case InlineAsm::isClobber:
+ case InlineAsm::isClobber: {
// Add the clobbered value to the operand list, so that the register
// allocator is aware that the physreg got clobbered.
+ const auto RegError =
+ getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
if (!OpInfo.AssignedRegs.Regs.empty())
OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind::Clobber,
false, 0, getCurSDLoc(), DAG,
AsmNodeOperands);
break;
}
+ }
}
// Finish up input operands. Set the input chain and add the flag last.
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 7fa83a5999dfe..04391dcfd4bb7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5620,8 +5620,8 @@ void TargetLowering::CollectTargetIntrinsicOperands(
std::pair<unsigned, const TargetRegisterClass *>
TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *RI,
- StringRef Constraint,
- MVT VT) const {
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const {
if (!Constraint.starts_with("{"))
return std::make_pair(0u, static_cast<TargetRegisterClass *>(nullptr));
assert(*(Constraint.end() - 1) == '}' && "Not a brace enclosed constraint?");
@@ -5654,6 +5654,8 @@ TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *RI,
}
}
}
+ if (!R.second)
+ ErrMsg = "register is unavailable";
return R;
}
@@ -5842,12 +5844,13 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
+ std::string ErrMsg;
std::pair<unsigned, const TargetRegisterClass *> MatchRC =
getRegForInlineAsmConstraint(TRI, OpInfo.ConstraintCode,
- OpInfo.ConstraintVT);
+ OpInfo.ConstraintVT, ErrMsg);
std::pair<unsigned, const TargetRegisterClass *> InputRC =
getRegForInlineAsmConstraint(TRI, Input.ConstraintCode,
- Input.ConstraintVT);
+ Input.ConstraintVT, ErrMsg);
if ((OpInfo.ConstraintVT.isInteger() !=
Input.ConstraintVT.isInteger()) ||
(MatchRC.second != InputRC.second)) {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 81e15185f985d..704c899328a18 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -1270,7 +1270,8 @@ class AArch64TargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
const char *LowerXConstraint(EVT ConstraintVT) const override;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 1f198a92c0fa6..9a1a3d0cf795e 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -481,7 +481,8 @@ class SITargetLowering final : public AMDGPUTargetLowering {
uint32_t RsrcDword1, uint64_t RsrcDword2And3) const;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
ConstraintType getConstraintType(StringRef Constraint) const override;
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
std::vector<SDValue> &Ops,
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index a255e9b6fc365..591e515c17943 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -529,7 +529,8 @@ class VectorType;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
const char *LowerXConstraint(EVT ConstraintVT) const override;
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index f605795934532..5f7004b5fbb1f 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -131,7 +131,8 @@ class AVRTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
InlineAsm::ConstraintCode
getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index 42707949e864c..c04545a7fa2a9 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -51,7 +51,8 @@ class BPFTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
diff --git a/llvm/lib/Target/CSKY/CSKYISelLowering.h b/llvm/lib/Target/CSKY/CSKYISelLowering.h
index d59481af3c5ba..18ac4536ad640 100644
--- a/llvm/lib/Target/CSKY/CSKYISelLowering.h
+++ b/llvm/lib/Target/CSKY/CSKYISelLowering.h
@@ -92,7 +92,8 @@ class CSKYTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 3fd961f5a7462..8ab2fd26b7c64 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -299,7 +299,8 @@ class HexagonTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
// Intrinsics
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.h b/llvm/lib/Target/Lanai/LanaiISelLowering.h
index 5fa5444b51618..d00321dfdb849 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.h
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.h
@@ -99,7 +99,8 @@ class LanaiTargetLowering : public TargetLowering {
const MachineFunction &MF) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
ConstraintWeight
getSingleConstraintMatchWeight(AsmOperandInfo &Info,
const char *Constraint) const override;
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index fc5b36c2124e0..63ca6a7d32c3c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -323,7 +323,8 @@ class LoongArchTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
std::vector<SDValue> &Ops,
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h
index d00907775f928..69b48713bb1e2 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.h
+++ b/llvm/lib/Target/M68k/M68kISelLowering.h
@@ -160,7 +160,8 @@ class M68kTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
// Lower operand with C_Immediate and C_Other constraint type
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/llvm/lib/Target/MSP430/MSP430ISelLowering.h
index 667ad60338619..8c75b60915147 100644
--- a/llvm/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.h
@@ -108,7 +108,8 @@ namespace llvm {
getConstraintType(StringRef Constraint) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
/// isTruncateFree - Return true if it's free to truncate a value of type
/// Ty1 to type Ty2. e.g. On msp430 it's free to truncate a i16 value in
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 84ad40d6bbbe2..bd7ffea5d0ad6 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -637,7 +637,8 @@ class TargetRegisterClass;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. If hasMemory is
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
index 63262961b363e..1c4d7f64cdd4f 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
@@ -512,7 +512,8 @@ class NVPTXTargetLowering : public TargetLowering {
ConstraintType getConstraintType(StringRef Constraint) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
bool isVarArg,
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 0bdfdcd15441f..7fdddc1d2dff1 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -976,7 +976,8 @@ namespace llvm {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
/// function arguments in the caller parameter area. This is the actual
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index d1d0760d8ffd1..f9470ff0e65a6 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -638,7 +638,8 @@ class RISCVTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
std::vector<SDValue> &Ops,
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
index 77356b7512a73..492225046391f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
@@ -57,7 +57,8 @@ class SPIRVTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
unsigned
getNumRegisters(LLVMContext &Context, EVT VT,
std::optional<MVT> RegisterVT = std::nullopt) const override {
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 15d09bc930975..d95dae6514c45 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -94,7 +94,8 @@ namespace llvm {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 1e7285e3e0fc5..f713c66e0f064 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -512,7 +512,8 @@ class SystemZTargetLowering : public TargetLowering {
const char *getTargetNodeName(unsigned Opcode) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
TargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const override;
TargetLowering::ConstraintWeight
diff --git a/llvm/lib/Target/VE/VEISelLowering.h b/llvm/lib/Target/VE/VEISelLowering.h
index 8b9412d786625..9e603ce058290 100644
--- a/llvm/lib/Target/VE/VEISelLowering.h
+++ b/llvm/lib/Target/VE/VEISelLowering.h
@@ -319,7 +319,8 @@ class VETargetLowering : public TargetLowering {
ConstraintType getConstraintType(StringRef Constraint) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
/// } Inline Assembly
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index 7d9cfb7739e43..e2a0d4bcc1c4e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -64,7 +64,8 @@ class WebAssemblyTargetLowering final : public TargetLowering {
const char *getTargetNodeName(unsigned Opcode) const override;
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
bool isCheapToSpeculateCttz(Type *Ty) const override;
bool isCheapToSpeculateCtlz(Type *Ty) const override;
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 73405397aa6e8..aaf9507eebb9a 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58854,8 +58854,8 @@ static bool useEGPRInlineAsm(const X86Subtarget &Subtarget) {
std::pair<unsigned, const TargetRegisterClass *>
X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint,
- MVT VT) const {
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const {
// First, see if this is a constraint that directly corresponds to an LLVM
// register class.
if (Constraint.size() == 1) {
@@ -58888,6 +58888,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
if (VT == MVT::v64i1 || VT == MVT::i64)
return std::make_pair(0U, &X86::VK64RegClass);
}
+ ErrMsg = "register is unavailable without AVX512 or AVX512BW";
break;
case 'q': // GENERAL_REGS in 64-bit mode, Q_REGS in 32-bit mode.
if (Subtarget.is64Bit()) {
@@ -58941,6 +58942,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, useEGPRInlineAsm(Subtarget)
? &X86::GR64RegClass
: &X86::GR64_NOREX2RegClass);
+ ErrMsg = "couldn't allocate for type " + EVT(VT).getEVTString();
break;
case 'R': // LEGACY_REGS
if (VT == MVT::i8 || VT == MVT::i1)
@@ -58962,17 +58964,23 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &X86::RFP64RegClass);
if (VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f80)
return std::make_pair(0U, &X86::RFP80RegClass);
+ ErrMsg = "couldn't allocate for type " + EVT(VT).getEVTString();
break;
case 'y': // MMX_REGS if MMX allowed.
if (!Subtarget.hasMMX()) break;
return std::make_pair(0U, &X86::VR64RegClass);
case 'v':
case 'x': // SSE_REGS if SSE1 allowed or AVX_REGS if AVX allowed
- if (!Subtarget.hasSSE1()) break;
+ if (!Subtarget.hasSSE1()) {
+ ErrMsg = "register is unavailable without SSE1";
+ break;
+ }
bool VConstraint = (Constraint[0] == 'v');
switch (VT.SimpleTy) {
- default: break;
+ default:
+ ErrMsg = "couldn't allocate for type " + EVT(VT).getEVTString();
+ break;
// Scalar SSE types.
case MVT::f16:
if (VConstraint && Subtarget.hasFP16())
@@ -59043,14 +59051,18 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &X86::VR256RegClass);
break;
case MVT::v32f16:
- if (!Subtarget.hasFP16())
+ if (!Subtarget.hasFP16()) {
+ ErrMsg = "register is unavailable without AVX512FP16";
break;
+ }
if (VConstraint)
return std::make_pair(0U, &X86::VR512RegClass);
return std::make_pair(0U, &X86::VR512_0_15RegClass);
case MVT::v32bf16:
- if (!Subtarget.hasBF16())
+ if (!Subtarget.hasBF16()) {
+ ErrMsg = "register is unavailable without AVX512BF16";
break;
+ }
if (VConstraint)
return std::make_pair(0U, &X86::VR512RegClass);
return std::make_pair(0U, &X86::VR512_0_15RegClass);
@@ -59074,7 +59086,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
case 'i':
case 't':
case '2':
- return getRegForInlineAsmConstraint(TRI, "x", VT);
+ return getRegForInlineAsmConstraint(TRI, "x", VT, ErrMsg);
case 'm':
if (!Subtarget.hasMMX()) break;
return std::make_pair(0U, &X86::VR64RegClass);
@@ -59162,6 +59174,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
if (VT == MVT::v64i1 || VT == MVT::i64)
return std::make_pair(0U, &X86::VK64WMRegClass);
}
+ ErrMsg = "register is unavailable without AVX512 or AVX512BW";
break;
}
} else if (Constraint.size() == 2 && Constraint[0] == 'j') {
@@ -59197,7 +59210,8 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
// Use the default implementation in TargetLowering to convert the register
// constraint into a member of a register class.
std::pair<Register, const TargetRegisterClass*> Res;
- Res = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+ Res =
+ TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT, ErrMsg);
// Not found as a standard register?
if (!Res.second) {
@@ -59241,18 +59255,20 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return Res;
}
+ // Make sure it isn't a register that requires AVX512.
+ if (!Subtarget.hasAVX512() && isFRClass(*Res.second) &&
+ TRI->getEncodingValue(Res.first) & 0x10) {
+ // Register requires EVEX prefix.
+ ErrMsg = "register is unavailable without AVX512F";
+ return std::make_pair(0, nullptr);
+ }
+
// Make sure it isn't a register that requires 64-bit mode.
if (!Subtarget.is64Bit() &&
(isFRClass(*Res.second) || isGRClass(*Res.second)) &&
TRI->getEncodingValue(Res.first) >= 8) {
// Register requires REX prefix, but we're in 32-bit mode.
- return std::make_pair(0, nullptr);
- }
-
- // Make sure it isn't a register that requires AVX512.
- if (!Subtarget.hasAVX512() && isFRClass(*Res.second) &&
- TRI->getEncodingValue(Res.first) & 0x10) {
- // Register requires EVEX prefix.
+ ErrMsg = "register is unavailable in 32-bit mode";
return std::make_pair(0, nullptr);
}
@@ -59274,8 +59290,10 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
if (isGRClass(*Class)) {
unsigned Size = VT.getSizeInBits();
if (Size == 1) Size = 8;
- if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
+ if (Size != 8 && Size != 16 && Size != 32 && Size != 64) {
+ ErrMsg = "couldn't allocate for type " + EVT(VT).getEVTString();
return std::make_pair(0, nullptr);
+ }
Register DestReg = getX86SubSuperRegister(Res.first, Size);
if (DestReg.isValid()) {
bool is64Bit = Subtarget.is64Bit();
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 362daa98e1f8e..8e61c49b9a33b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1311,7 +1311,8 @@ namespace llvm {
/// error, this returns a register number of 0.
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
/// Return true if the addressing mode represented
/// by AM is legal for this target, for a load/store of the specified type.
diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.h b/llvm/lib/Target/XCore/XCoreISelLowering.h
index eaa36d40cba92..9a0a7b4c43b8d 100644
--- a/llvm/lib/Target/XCore/XCoreISelLowering.h
+++ b/llvm/lib/Target/XCore/XCoreISelLowering.h
@@ -185,7 +185,8 @@ namespace llvm {
// Inline asm support
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
- StringRef Constraint, MVT VT) const override;
+ StringRef Constraint, MVT VT,
+ std::string &ErrMsg) const override;
// Expand specifics
SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
index 887de29e7e672..02189734af4f8 100644
--- a/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
@@ -1,7 +1,7 @@
; RUN: not llc -o /dev/null -mattr=avx %s 2>&1 | FileCheck %s
target triple = "x86_64--"
-; CHECK: error: register 'XMM15' allocated for constraint '{xmm15}' does not match required type
+; CHECK: error: couldn't allocate input reg for constraint '{xmm15}': register 'XMM15' allocated for constraint '{xmm15}' does not match required type v8i32
define void @test1() nounwind {
entry:
tail call void asm sideeffect "call dummy", "{xmm15},~{dirflag},~{fpsr},~{flags}"(<8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>) #1
diff --git a/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch.ll b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch.ll
index 513f88b05dd9b..ac79435b6136f 100644
--- a/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch.ll
@@ -1,19 +1,19 @@
; RUN: not llc -o /dev/null %s 2>&1 | FileCheck %s
target triple = "x86_64--"
-; CHECK: error: couldn't allocate output register for constraint '{ax}'
+; CHECK: error: couldn't allocate output register for constraint '{ax}': couldn't allocate for type i128
define i128 @blup() {
%v = tail call i128 asm "", "={ax},0"(i128 0)
ret i128 %v
}
-; CHECK: error: couldn't allocate input reg for constraint 'r'
+; CHECK: error: couldn't allocate input reg for constraint 'r': couldn't allocate for type f80
define void @fp80(x86_fp80) {
tail call void asm sideeffect "", "r"(x86_fp80 %0)
ret void
}
-; CHECK: error: couldn't allocate input reg for constraint 'f'
+; CHECK: error: couldn't allocate input reg for constraint 'f': couldn't allocate for type i128
define void @f_constraint_i128(ptr %0) {
%2 = load i128, ptr %0, align 16
tail call void asm sideeffect "", "f"(i128 %2)
diff --git a/llvm/test/CodeGen/X86/asm-reject-rex.ll b/llvm/test/CodeGen/X86/asm-reject-rex.ll
index f9719b84816a6..7456f5a354d60 100644
--- a/llvm/test/CodeGen/X86/asm-reject-rex.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-rex.ll
@@ -2,19 +2,19 @@
; Make sure X32 still works.
; RUN: llc -o /dev/null %s -mtriple=x86_64-linux-gnux32
-; CHECK: error: couldn't allocate output register for constraint '{xmm8}'
+; CHECK: error: couldn't allocate output register for constraint '{xmm8}': register is unavailable in 32-bit mode
define i64 @blup() {
%v = tail call i64 asm "", "={xmm8},0"(i64 0)
ret i64 %v
}
-; CHECK: error: couldn't allocate output register for constraint '{r8d}'
+; CHECK: error: couldn't allocate output register for constraint '{r8d}': register is unavailable in 32-bit mode
define i32 @foo() {
%v = tail call i32 asm "", "={r8d},0"(i32 0)
ret i32 %v
}
-; CHECK: error: couldn't allocate output register for constraint '{rax}'
+; CHECK: error: couldn't allocate output register for constraint '{rax}': register is unavailable
define i64 @bar() {
%v = tail call i64 asm "", "={rax},0"(i64 0)
ret i64 %v
diff --git a/llvm/test/CodeGen/X86/asm-reject-vk32-vk64.ll b/llvm/test/CodeGen/X86/asm-reject-vk32-vk64.ll
index 12d148a3a74b6..2392745dddea8 100644
--- a/llvm/test/CodeGen/X86/asm-reject-vk32-vk64.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-vk32-vk64.ll
@@ -1,28 +1,28 @@
; RUN: not llc -o /dev/null %s -mtriple=x86_64-unknown-unknown -mattr=avx512f 2>&1 | FileCheck %s
; RUN: not llc -o /dev/null %s -mtriple=i386-unknown-unknown -mattr=avx512f 2>&1 | FileCheck %s
-; CHECK: error: couldn't allocate input reg for constraint 'Yk'
+; CHECK: error: couldn't allocate input reg for constraint 'Yk': register is unavailable without AVX512 or AVX512BW
define <8 x i64> @mask_Yk_i32(i32 %msk, <8 x i64> %x, <8 x i64> %y) {
entry:
%0 = tail call <8 x i64> asm "vpaddw\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i32 %msk, <8 x i64> %x, <8 x i64> %y)
ret <8 x i64> %0
}
-; CHECK: error: couldn't allocate input reg for constraint 'Yk'
+; CHECK: error: couldn't allocate input reg for constraint 'Yk': register is unavailable without AVX512 or AVX512BW
define <8 x i64> @mask_Yk_i64(i64 %msk, <8 x i64> %x, <8 x i64> %y) {
entry:
%0 = tail call <8 x i64> asm "vpaddb\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i64 %msk, <8 x i64> %x, <8 x i64> %y)
ret <8 x i64> %0
}
-; CHECK: error: couldn't allocate output register for constraint 'k'
+; CHECK: error: couldn't allocate output register for constraint 'k': register is unavailable without AVX512 or AVX512BW
define i32 @k_wise_op_i32(i32 %msk_src1, i32 %msk_src2) {
entry:
%0 = tail call i32 asm "kandd\09$2, $1, $0", "=k,k,k,~{dirflag},~{fpsr},~{flags}"(i32 %msk_src1, i32 %msk_src2)
ret i32 %0
}
-; CHECK: error: couldn't allocate output register for constraint 'k'
+; CHECK: error: couldn't allocate output register for constraint 'k': register is unavailable without AVX512 or AVX512BW
define i64 @k_wise_op_i64(i64 %msk_src1, i64 %msk_src2) {
entry:
%0 = tail call i64 asm "kandq\09$2, $1, $0", "=k,k,k,~{dirflag},~{fpsr},~{flags}"(i64 %msk_src1, i64 %msk_src2)
diff --git a/llvm/test/CodeGen/X86/asm-reject-x87-int.ll b/llvm/test/CodeGen/X86/asm-reject-x87-int.ll
index 233a0df5ba46b..e79d358aa3075 100644
--- a/llvm/test/CodeGen/X86/asm-reject-x87-int.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-x87-int.ll
@@ -22,7 +22,7 @@
%struct.float4 = type { float }
-; CHECK: error: couldn't allocate output register for constraint '{st}'
+; CHECK: error: couldn't allocate output register for constraint '{st}': register is unavailable
define dso_local i32 @foo() {
entry:
%retval = alloca i32, align 4
diff --git a/llvm/test/CodeGen/X86/asm-reject-xmm16.ll b/llvm/test/CodeGen/X86/asm-reject-xmm16.ll
index 52915d9558b9c..b898d16dcd45f 100644
--- a/llvm/test/CodeGen/X86/asm-reject-xmm16.ll
+++ b/llvm/test/CodeGen/X86/asm-reject-xmm16.ll
@@ -1,7 +1,8 @@
-; RUN: not llc -o /dev/null %s -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s
-; RUN: not llc -o /dev/null %s -mtriple=i386-unknown-unknown -mattr=avx512vl 2>&1 | FileCheck %s
+; RUN: not llc -o /dev/null %s -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s -check-prefix X64
+; RUN: not llc -o /dev/null %s -mtriple=i386-unknown-unknown -mattr=avx512vl 2>&1 | FileCheck %s -check-prefix X86
-; CHECK: error: couldn't allocate output register for constraint '{xmm16}'
+; X64: error: couldn't allocate output register for constraint '{xmm16}': register is unavailable without AVX512F
+; X86: error: couldn't allocate output register for constraint '{xmm16}': register is unavailable in 32-bit mode
define i64 @blup() {
%v = tail call i64 asm "", "={xmm16},0"(i64 0)
ret i64 %v
diff --git a/llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll
index e153387d16e72..d355a5ca5bad9 100644
--- a/llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll
+++ b/llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll
@@ -18,7 +18,7 @@ entry:
; FP16: %[[REG1:.*]]:vr512_0_15 = COPY %1
; FP16: %[[REG2:.*]]:vr512_0_15 = COPY %2
; FP16: INLINEASM &"vaddph\09$3, $2, $0 {$1}", 0 /* attdialect */, {{.*}}, def %{{.*}}, {{.*}}, %{{.*}}, {{.*}}, %[[REG1]], {{.*}}, %[[REG2]], 12 /* clobber */, implicit-def early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def early-clobber $eflags
-; CHECK-STDERR: couldn't allocate output register for constraint 'x'
+; CHECK-STDERR: couldn't allocate output register for constraint 'x': register is unavailable without AVX512FP16
define <32 x half> @mask_Yk_f16(i8 signext %msk, <32 x half> %x, <32 x half> %y) {
entry:
%0 = tail call <32 x half> asm "vaddph\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i8 %msk, <32 x half> %x, <32 x half> %y)
@@ -29,7 +29,7 @@ entry:
; FP16: %[[REG1:.*]]:vr512_0_15 = COPY %1
; FP16: %[[REG2:.*]]:vr512_0_15 = COPY %2
; FP16: INLINEASM &"vaddph\09$3, $2, $0 {$1}", 0 /* attdialect */, {{.*}}, def %{{.*}}, {{.*}}, %{{.*}}, {{.*}}, %[[REG1]], {{.*}}, %[[REG2]], 12 /* clobber */, implicit-def early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def early-clobber $eflags
-; CHECK-STDERR: couldn't allocate output register for constraint 'x'
+; CHECK-STDERR: couldn't allocate output register for constraint 'x': register is unavailable without AVX512BF16
define <32 x bfloat> @mask_Yk_bf16(i8 signext %msk, <32 x bfloat> %x, <32 x bfloat> %y) {
entry:
%0 = tail call <32 x bfloat> asm "vaddph\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i8 %msk, <32 x bfloat> %x, <32 x bfloat> %y)
diff --git a/llvm/test/CodeGen/X86/inline-asm-x-i128.ll b/llvm/test/CodeGen/X86/inline-asm-x-i128.ll
index 7aee1d175494e..281921ff570a8 100644
--- a/llvm/test/CodeGen/X86/inline-asm-x-i128.ll
+++ b/llvm/test/CodeGen/X86/inline-asm-x-i128.ll
@@ -4,7 +4,7 @@
; RUN: not llc < %s -mtriple=i386-unknown-linux-gnu 2>&1 | FileCheck %s --check-prefix=ERROR
; For 32-bit we still error since __int128 isn't supported in the frontend.
-; ERROR: error: couldn't allocate output register for constraint 'x'
+; ERROR: error: couldn't allocate output register for constraint 'x': register is unavailable without SSE1
define { i64, i64 } @foo(i64 %0, i64 %1) {
; CHECK-LABEL: foo:
diff --git a/llvm/test/CodeGen/X86/pr37359.ll b/llvm/test/CodeGen/X86/pr37359.ll
index 5032855ff3e9d..3a272e315f8f6 100644
--- a/llvm/test/CodeGen/X86/pr37359.ll
+++ b/llvm/test/CodeGen/X86/pr37359.ll
@@ -3,7 +3,7 @@ target triple = "x86_64--"
@a = global i32 0, align 4
-; CHECK: error: couldn't allocate input reg for constraint 'x'
+; CHECK: error: couldn't allocate input reg for constraint 'x': couldn't allocate for type i1
define i32 @main() {
entry:
%0 = load i32, ptr @a, align 4
diff --git a/llvm/test/CodeGen/X86/pr50907.ll b/llvm/test/CodeGen/X86/pr50907.ll
index c6af54d5ab8b4..95de1b1fdddf4 100644
--- a/llvm/test/CodeGen/X86/pr50907.ll
+++ b/llvm/test/CodeGen/X86/pr50907.ll
@@ -2,7 +2,7 @@
; RUN: not llc -o /dev/null %s 2>&1 | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
-; CHECK: error: couldn't allocate input reg for constraint 'r'
+; CHECK: error: couldn't allocate input reg for constraint 'r': couldn't allocate for type v8i16
define i32 @f2() #0 {
entry:
%retval = alloca i32, align 4
More information about the llvm-commits
mailing list