[llvm] [Hexagon] Add XQFloat post-RA compliance checker (PR #207082)
Fateme Hosseini via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 09:28:04 PDT 2026
https://github.com/fhossein-quic updated https://github.com/llvm/llvm-project/pull/207082
>From ba2ff5e5a2f3027d0894dbb2b4b3ebd57b604cb7 Mon Sep 17 00:00:00 2001
From: Fateme Hosseini <fhossein at qti.qualcomm.com>
Date: Tue, 30 Jun 2026 07:30:59 -0700
Subject: [PATCH] [Hexagon] Add XQFloat post-RA compliance checker
Introduce XqfPostRADiagnosis to verify qf use-def correctness
after register allocation. Acts as a diagnostic/debugger for
XQFloat implementation. Off by default, enabled with
-enable-postra-xqf-check.
Co-authored-by: Santanu Das <quic_santdas at quicinc.com>
---
.../Target/Hexagon/HexagonPostRAHandleQFP.cpp | 245 ++++++++++++------
.../CodeGen/Hexagon/autohvx/xqf-multi-conv.ll | 133 ++++++++++
.../autohvx/xqf-postra-conv-double2.ll | 2 +-
.../Hexagon/autohvx/xqf-postra-fakereg.ll | 2 +-
.../Hexagon/autohvx/xqf-postra-subreg2.ll | 2 +-
.../Hexagon/autohvx/xqf-postra-subreg3.ll | 45 ++++
.../Hexagon/autohvx/xqf-postra-warnings.ll | 60 +++++
7 files changed, 412 insertions(+), 77 deletions(-)
create mode 100644 llvm/test/CodeGen/Hexagon/autohvx/xqf-multi-conv.ll
create mode 100644 llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg3.ll
create mode 100644 llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-warnings.ll
diff --git a/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp b/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp
index 06ee6e5fa0414..9eab2bec3f2e0 100644
--- a/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp
@@ -92,68 +92,9 @@ cl::opt<bool> DisablePostRAHandleQFloat(
cl::desc("Disable handling of Qfloat spills/refills after register "
"allocation."));
-// This static function gets all reached uses of a def.
-// When it encounters a phi node, it goes over the
-// reached uses of the phi node too.
-static void getAllRealUses(NodeAddr<DefNode *> DA, NodeSet &UNodeSet,
- Liveness *L, DataFlowGraph *G,
- bool comprehensive = false) {
- RegisterRef DR = DA.Addr->getRegRef(*G);
- NodeAddr<StmtNode *> DefStmt = DA.Addr->getOwner(*G);
- MachineInstr *Instr = DefStmt.Addr->getCode();
- auto UseSet = L->getAllReachedUses(DR, DA);
-
- for (auto UI : UseSet) {
- NodeAddr<UseNode *> UA = G->addr<UseNode *>(UI);
-
- /*LLVM_DEBUG(
- NodeAddr<StmtNode *> UseStmt = UA.Addr->getOwner(*G);
- MachineInstr* UseInstr = UseStmt.Addr->getCode();
- if (UseInstr != nullptr)
- {dbgs() << "\t\t[Reached Use]: "; UseInstr->dump();}
- );*/
-
- MachineFunction *MF = Instr->getMF();
- const auto &HRI = MF->getSubtarget<HexagonSubtarget>().getRegisterInfo();
- Register RR = UA.Addr->getRegRef(*G).Id;
- if (HRI->isFakeReg(RR))
- continue;
-
- if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
- NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*G);
- NodeId id = PA.Id;
- const Liveness::RefMap &phiUse = L->getRealUses(id);
- for (auto I : phiUse) {
- if (!G->getPRI().alias(RegisterRef(I.first), DR))
- continue;
- auto phiUseSet = I.second;
- for (auto phiUI : phiUseSet) {
- NodeAddr<UseNode *> phiUA = G->addr<UseNode *>(phiUI.first);
- UNodeSet.insert(phiUA.Id);
- }
- }
- } else {
- // FIXME Due to bug in RDF, check if the reaching def of the use
- // reaches this instruction
- if (comprehensive) {
- UNodeSet.insert(UA.Id);
- continue;
- }
- NodeAddr<StmtNode *> UseStmt = UA.Addr->getOwner(*G);
- for (NodeAddr<UseNode *> UA : UseStmt.Addr->members_if(G->IsUse, *G)) {
- NodeId QFPDefNode = UA.Addr->getReachingDef();
- NodeAddr<DefNode *> RegDef = G->addr<DefNode *>(QFPDefNode);
- // FIXME Reaching def computation error
- if (QFPDefNode == 0)
- continue;
- NodeAddr<StmtNode *> RegStmt = RegDef.Addr->getOwner(*G);
- MachineInstr *ReachDefInstr = RegStmt.Addr->getCode();
- if (ReachDefInstr && ReachDefInstr == Instr)
- UNodeSet.insert(UA.Id);
- }
- }
- }
-}
+static cl::opt<bool> EnablePostRAXqfCompliance(
+ "enable-postra-xqf-check", cl::init(false),
+ cl::desc("Enable ABI compliance for xqf operands post regalloc."));
namespace llvm {
FunctionPass *createHexagonPostRAHandleQFP();
@@ -250,7 +191,7 @@ class HexagonPostRAHandleQFP : public MachineFunctionPass {
MapVector<MachineInstr *, unsigned> QFNonSatMIs;
// Stores the qf-generating vmul/vadd/etc. nodes with mutiple reaching defs
- std::set<NodeId> PossibleMultiReachDefs;
+ std::set<NodeAddr<StmtNode *>> PossibleMultiReachDefs;
// Qf generating instructions to ignore. Do not insert conversion instruction
// to sf/hf from qf, if the instr is present in this list; since that means
// a conversion has already been inserted after the instruction.
@@ -260,7 +201,8 @@ class HexagonPostRAHandleQFP : public MachineFunctionPass {
enum class RegType { qf32, qf16, qf32_double, qf16_double, ieee, undefined };
// Stores the copy instructions which their reaching def, along with the op
// type
- std::map<std::pair<NodeId, NodeId>, RegType> QFCopys;
+ std::map<std::pair<NodeAddr<DefNode *>, NodeAddr<DefNode *>>, RegType>
+ QFCopys;
// Stores the reaching defs of copies whose result has to be converted to IEEE
DenseMap<MachineInstr *, RegType> ReachDefOfCopies;
@@ -310,6 +252,150 @@ class HexagonPostRAHandleQFP : public MachineFunctionPass {
// instead of IEEE type. This diagnostic pass can be used
// as a final verifier for XQF implementation. Turned off by
// default
+class XqfPostRADiagnosis {
+public:
+ XqfPostRADiagnosis(DataFlowGraph &_G, Liveness &_L,
+ const HexagonInstrInfo *_HII)
+ : G(&_G), L(&_L), HII(_HII) {}
+ // Deleting default constructor to handle misconstruction
+ XqfPostRADiagnosis() = delete;
+
+ void runCompliance() const;
+ void print_warning(Twine &, MachineInstr *, MachineInstr *) const;
+
+private:
+ DataFlowGraph *G = nullptr;
+ Liveness *L = nullptr;
+ const HexagonInstrInfo *HII = nullptr;
+};
+
+void XqfPostRADiagnosis::print_warning(Twine &wstr, MachineInstr *DefMI,
+ MachineInstr *UseMI) const {
+#ifndef NDEBUG
+ dbgs() << wstr;
+ dbgs() << "\n\tDef:";
+ DefMI->dump();
+ // dbgs() << "\t" << DefMI->getParent()->getName();
+ dbgs() << "\tUse:";
+ UseMI->dump();
+ // dbgs() << "\t" << UseMI->getParent()->getName();
+#endif // NDEBUG
+}
+
+// This static function gets all reached uses of a def.
+// When it encounters a phi node, it goes over the
+// reached uses of the phi node too.
+static void getAllRealUses(NodeAddr<DefNode *> DA, NodeSet &UNodeSet,
+ Liveness *L, DataFlowGraph *G,
+ bool comprehensive = false) {
+ RegisterRef DR = DA.Addr->getRegRef(*G);
+ NodeAddr<StmtNode *> DefStmt = DA.Addr->getOwner(*G);
+ MachineInstr *Instr = DefStmt.Addr->getCode();
+ auto UseSet = L->getAllReachedUses(DR, DA);
+
+ for (auto UI : UseSet) {
+ NodeAddr<UseNode *> UA = G->addr<UseNode *>(UI);
+
+ /*LLVM_DEBUG(
+ NodeAddr<StmtNode *> UseStmt = UA.Addr->getOwner(*G);
+ MachineInstr* UseInstr = UseStmt.Addr->getCode();
+ if (UseInstr != nullptr)
+ {dbgs() << "\t\t[Reached Use]: "; UseInstr->dump();}
+ );*/
+
+ MachineFunction *MF = Instr->getMF();
+ const auto &HRI = MF->getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ Register RR = UA.Addr->getRegRef(*G).Id;
+ if (HRI->isFakeReg(RR))
+ continue;
+
+ if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
+ NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*G);
+ NodeId id = PA.Id;
+ const Liveness::RefMap &phiUse = L->getRealUses(id);
+ for (auto I : phiUse) {
+ if (!G->getPRI().alias(RegisterRef(I.first), DR))
+ continue;
+ auto phiUseSet = I.second;
+ for (auto phiUI : phiUseSet) {
+ NodeAddr<UseNode *> phiUA = G->addr<UseNode *>(phiUI.first);
+ UNodeSet.insert(phiUA.Id);
+ }
+ }
+ } else {
+ // FIXME Due to bug in RDF, check if the reaching def of the use
+ // reaches this instruction
+ if (comprehensive) {
+ UNodeSet.insert(UA.Id);
+ continue;
+ }
+ NodeAddr<StmtNode *> UseStmt = UA.Addr->getOwner(*G);
+ for (NodeAddr<UseNode *> UA : UseStmt.Addr->members_if(G->IsUse, *G)) {
+ NodeId QFPDefNode = UA.Addr->getReachingDef();
+ NodeAddr<DefNode *> RegDef = G->addr<DefNode *>(QFPDefNode);
+ // FIXME Reaching def computation error
+ if (QFPDefNode == 0)
+ continue;
+ NodeAddr<StmtNode *> RegStmt = RegDef.Addr->getOwner(*G);
+ MachineInstr *ReachDefInstr = RegStmt.Addr->getCode();
+ if (ReachDefInstr && ReachDefInstr == Instr)
+ UNodeSet.insert(UA.Id);
+ }
+ }
+ }
+}
+
+void XqfPostRADiagnosis::runCompliance() const {
+ NodeAddr<FuncNode *> FA = G->getFunc();
+ for (NodeAddr<BlockNode *> BA : FA.Addr->members(*G)) {
+ for (auto IA : BA.Addr->members(*G)) {
+ if (!G->IsCode<NodeAttrs::Stmt>(IA))
+ continue;
+ NodeAddr<StmtNode *> SA = IA;
+ MachineInstr *DefMI = SA.Addr->getCode();
+ if (DefMI->isDebugInstr() || DefMI->isInlineAsm())
+ continue;
+ auto NodeBase = SA.Addr->members_if(G->IsDef, *G);
+ if (NodeBase.empty())
+ continue;
+ NodeAddr<DefNode *> DfNode = NodeBase.front();
+
+ NodeSet UseSet;
+ getAllRealUses(DfNode, UseSet, L, G, true);
+ for (auto UI : UseSet) {
+ NodeAddr<UseNode *> UA = G->addr<UseNode *>(UI);
+ if (UA.Addr->getFlags() & NodeAttrs::PhiRef)
+ continue;
+ NodeAddr<StmtNode *> UseStmt = UA.Addr->getOwner(*G);
+ MachineInstr *UseMI = UseStmt.Addr->getCode();
+ if (UseMI->isDebugInstr() || UseMI->isInlineAsm())
+ continue;
+ unsigned OpNo = UA.Addr->getOp().getOperandNo();
+ if (HII->usesQF32Operand(UseMI, OpNo) && !HII->isQFP32Instr(DefMI)) {
+ Twine wstr(Twine("Mismatch: sf type used as qf32 at operand ")
+ .concat(Twine(OpNo)));
+ print_warning(wstr, DefMI, UseMI);
+ } else if (!HII->usesQF32Operand(UseMI, OpNo) &&
+ HII->isQFP32Instr(DefMI)) {
+ Twine wstr(Twine("Mismatch: qf32 type used as sf at operand ")
+ .concat(Twine(OpNo)));
+ print_warning(wstr, DefMI, UseMI);
+ } else if (HII->usesQF16Operand(UseMI, OpNo) &&
+ !HII->isQFP16Instr(DefMI)) {
+ Twine wstr(Twine("Mismatch: hf type used as qf16 at operand ")
+ .concat(Twine(OpNo)));
+ print_warning(wstr, DefMI, UseMI);
+ } else if (!HII->usesQF16Operand(UseMI, OpNo) &&
+ HII->isQFP16Instr(DefMI)) {
+ Twine wstr(Twine("Mismatch: qf16 type used as hf at operand ")
+ .concat(Twine(OpNo)));
+ print_warning(wstr, DefMI, UseMI);
+ }
+ }
+ }
+ }
+}
+
char HexagonPostRAHandleQFP::ID = 0;
namespace llvm {
@@ -952,7 +1038,7 @@ void HexagonPostRAHandleQFP::collectCopies(NodeAddr<StmtNode *> *StNode) {
// If the reaching def is a COPY,collect it with reg type ieee
if (ReachDefInstr->getOpcode() == TargetOpcode::COPY) {
- auto pairKey = std::make_pair(CopyDef.Id, RegDef.Id);
+ auto pairKey = std::make_pair(CopyDef, RegDef);
QFCopys[pairKey] = RegType::ieee;
continue;
}
@@ -988,7 +1074,7 @@ void HexagonPostRAHandleQFP::collectCopies(NodeAddr<StmtNode *> *StNode) {
else
continue;
}
- auto pairKey = std::make_pair(CopyDef.Id, RegDef.Id);
+ auto pairKey = std::make_pair(CopyDef, RegDef);
QFCopys[pairKey] = RegT;
}
}
@@ -1072,8 +1158,8 @@ void HexagonPostRAHandleQFP::collectQFUses(NodeAddr<DefNode *> RegDef,
Register UsedReg = UA.Addr->getRegRef(*DFG).Id;
if (QFPSatInstsMap.find(UseMI->getOpcode()) != QFPSatInstsMap.end()) {
- if (PossibleMultiReachDefs.count(UseStmt.Id) == 0) {
- PossibleMultiReachDefs.insert(UseStmt.Id);
+ if (PossibleMultiReachDefs.count(UseStmt) == 0) {
+ PossibleMultiReachDefs.insert(UseStmt);
LLVM_DEBUG(dbgs() << "\n[Collect instr with possible multidef]:";
UseMI->dump());
}
@@ -1094,15 +1180,14 @@ bool HexagonPostRAHandleQFP::HandleMultiReachingDefs() {
// But it is not expected to since if any instruction has multiple
// definitions it should already be present in it.
for (auto It : PossibleMultiReachDefs) {
- NodeAddr<StmtNode *> Stmt = DFG->addr<StmtNode *>(It);
- MachineInstr *Instr = Stmt.Addr->getCode();
+ MachineInstr *Instr = It.Addr->getCode();
// get the op type for the original instruction.
// True is sf/hf, false is qf
auto Pair = QFUsesMap[Instr];
unsigned short UseNo = 1;
// Iterate over the operands
- for (NodeAddr<UseNode *> UA : Stmt.Addr->members_if(DFG->IsUse, *DFG)) {
+ for (NodeAddr<UseNode *> UA : It.Addr->members_if(DFG->IsUse, *DFG)) {
// If the type is qf for the operand,
// we skip since there is no scope for mismatch
@@ -1406,7 +1491,7 @@ bool HexagonPostRAHandleQFP::HandleCopies() {
for (auto It : QFCopys) {
// Get details of the copy node
- NodeAddr<DefNode *> CopyNode = DFG->addr<DefNode *>(It.first.first);
+ NodeAddr<DefNode *> CopyNode = It.first.first;
NodeAddr<StmtNode *> StNode = CopyNode.Addr->getOwner(*DFG);
[[maybe_unused]] auto *CopyMI = StNode.Addr->getCode();
LLVM_DEBUG(dbgs() << "\nHandling Reaching Defs of COPY: "; CopyMI->dump();
@@ -1433,7 +1518,7 @@ bool HexagonPostRAHandleQFP::HandleCopies() {
if (RTy != RegType::ieee) {
// get details of the reaching def node
- NodeAddr<DefNode *> ReachDefNode = DFG->addr<DefNode *>(It.first.second);
+ NodeAddr<DefNode *> ReachDefNode = It.first.second;
NodeAddr<StmtNode *> StNode = ReachDefNode.Addr->getOwner(*DFG);
auto *ReachingDef = StNode.Addr->getCode();
@@ -1459,7 +1544,7 @@ bool HexagonPostRAHandleQFP::HandleCopies() {
for (auto It : QFCopys) {
// Get details of the copy node
- NodeAddr<DefNode *> CopyNode = DFG->addr<DefNode *>(It.first.first);
+ NodeAddr<DefNode *> CopyNode = It.first.first;
NodeAddr<StmtNode *> StNode = CopyNode.Addr->getOwner(*DFG);
auto *CopyMI = StNode.Addr->getCode();
LLVM_DEBUG(dbgs() << "\nHandling COPY: "; CopyMI->dump());
@@ -1737,6 +1822,18 @@ bool HexagonPostRAHandleQFP::runOnMachineFunction(MachineFunction &MF) {
QFUsesMap.clear();
IgnoreInsertConvList.clear();
+ // Option if enabled, checks for qf use-def mismatches
+ if (EnablePostRAXqfCompliance) {
+ dbgs() << "\nChecking for ABI compliance for XQF post register \
+allocation for function: "
+ << MF.getName() << "\n";
+ DataFlowGraph DFG(MF, *HII, *HRI, *MDT, MDF);
+ DFG.build();
+ Liveness LV(*MRI, DFG);
+ LV.computeLiveIns();
+ XqfPostRADiagnosis VDiag(DFG, LV, HII);
+ VDiag.runCompliance();
+ }
return Changed;
}
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-multi-conv.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-multi-conv.ll
new file mode 100644
index 0000000000000..2f1a517aee1da
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-multi-conv.ll
@@ -0,0 +1,133 @@
+; Checks for presence of any mismatch, ie. an use of qf operand
+; as a sf/hf type or vice versa
+
+; RUN: llc -O2 -march=hexagon -mcpu=hexagonv79 -force-hvx-float -enable-xqf-gen=true \
+; RUN: -hexagon-qfloat-mode=ieee -mattr=+hvxv79,+hvx-length128B \
+; RUN: -enable-postra-xqf-check 2>&1 < %s -o /dev/null | FileCheck %s
+; RUN: llc -O2 -march=hexagon -mcpu=hexagonv81 -force-hvx-float -enable-xqf-gen=true \
+; RUN: -hexagon-qfloat-mode=ieee -mattr=+hvxv81,+hvx-length128B \
+; RUN: -enable-postra-xqf-check 2>&1 < %s -o /dev/null | FileCheck %s
+
+; CHECK: Checking for ABI compliance for XQF post register allocation
+; CHECK-NOT: Mismatch:
+
+define i32 @qhmath_hvx_sin_af(ptr noalias noundef %input, ptr noalias noundef %output) #0 {
+entry:
+ %0 = tail call i32 @llvm.hexagon.A2.min(i32 0, i32 64)
+ %cmp10100 = icmp sgt i32 %0, 0
+ br i1 %cmp10100, label %for.body12.lr.ph, label %for.cond.loopexit
+
+for.cond.loopexit: ; preds = %for.body12, %entry
+ ret i32 0
+
+for.body12.lr.ph: ; preds = %entry
+ %1 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 1065353216)
+ %2 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 -2147483648)
+ %3 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 1067645315)
+ %4 = tail call <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32> %1, <32 x i32> zeroinitializer)
+ %5 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 -1090519040)
+ %6 = tail call <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32> %5, <32 x i32> zeroinitializer)
+ %7 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 1026206373)
+ %8 = tail call <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32> %7, <32 x i32> zeroinitializer)
+ %9 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 -1162475884)
+ %10 = tail call <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32> %9, <32 x i32> zeroinitializer)
+ %11 = tail call <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32> zeroinitializer, <32 x i32> zeroinitializer)
+ %12 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 2147483647)
+ br label %for.body12
+
+for.body12: ; preds = %for.body12, %for.body12.lr.ph
+ %j.0104 = phi i32 [ 0, %for.body12.lr.ph ], [ %inc, %for.body12 ]
+ %optr.1102 = phi ptr [ %output, %for.body12.lr.ph ], [ %incdec.ptr14, %for.body12 ]
+ %sline1p.1101 = phi <32 x i32> [ zeroinitializer, %for.body12.lr.ph ], [ %13, %for.body12 ]
+ %13 = load <32 x i32>, ptr null, align 128
+ %14 = tail call <32 x i32> @llvm.hexagon.V6.valignb.128B(<32 x i32> %13, <32 x i32> %sline1p.1101, i32 0)
+ %15 = tail call <128 x i1> @llvm.hexagon.V6.vgtsf.128B(<32 x i32> %14, <32 x i32> zeroinitializer)
+ %16 = tail call <32 x i32> @llvm.hexagon.V6.vxor.128B(<32 x i32> %14, <32 x i32> %2)
+ %17 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> %15, <32 x i32> %14, <32 x i32> %16)
+ %18 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.sf.128B(<32 x i32> %17, <32 x i32> %3)
+ %19 = tail call <32 x i32> @llvm.hexagon.V6.vconv.sf.qf32.128B(<32 x i32> %18)
+ %20 = tail call <128 x i1> @llvm.hexagon.V6.vgtuw.128B(<32 x i32> %19, <32 x i32> %12)
+ %21 = lshr <32 x i32> %19, <i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23>
+ %and.i.i = and <32 x i32> %21, <i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255, i32 255>
+ %sub.i.i = add nsw <32 x i32> %and.i.i, <i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127, i32 -127>
+ %22 = tail call <32 x i32> @llvm.hexagon.V6.vmaxw.128B(<32 x i32> %sub.i.i, <32 x i32> zeroinitializer)
+ %sub1.i.i = sub <32 x i32> <i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23, i32 23>, %22
+ %23 = tail call <32 x i32> @llvm.hexagon.V6.vmaxw.128B(<32 x i32> %sub1.i.i, <32 x i32> zeroinitializer)
+ %shl.i.i = shl nuw <32 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %22
+ %24 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> zeroinitializer, <32 x i32> zeroinitializer, <32 x i32> %shl.i.i)
+ %25 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> %20, <32 x i32> zeroinitializer, <32 x i32> %24)
+ %shl5.neg.i.i = shl <32 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %23
+ %and7.i.i = and <32 x i32> %shl5.neg.i.i, %19
+ %26 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> zeroinitializer, <32 x i32> zeroinitializer, <32 x i32> %and7.i.i)
+ %27 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> zeroinitializer, <32 x i32> zeroinitializer, <32 x i32> %26)
+ %28 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.sf.128B(<32 x i32> zeroinitializer, <32 x i32> %27)
+ %29 = tail call <32 x i32> @llvm.hexagon.V6.vconv.sf.qf32.128B(<32 x i32> %28)
+ %30 = tail call <32 x i32> @llvm.hexagon.V6.vsub.sf.128B(<32 x i32> %17, <32 x i32> %29)
+ %31 = tail call <32 x i32> @llvm.hexagon.V6.vand.128B(<32 x i32> %25, <32 x i32> zeroinitializer)
+ %32 = tail call <128 x i1> @llvm.hexagon.V6.veqw.128B(<32 x i32> %31, <32 x i32> zeroinitializer)
+ %33 = tail call <128 x i1> @llvm.hexagon.V6.pred.xor.128B(<128 x i1> %15, <128 x i1> %32)
+ %34 = tail call <32 x i32> @llvm.hexagon.V6.vconv.sf.qf32.128B(<32 x i32> %30)
+ %35 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> zeroinitializer, <32 x i32> %34, <32 x i32> zeroinitializer)
+ %36 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.sf.128B(<32 x i32> %35, <32 x i32> %35)
+ %37 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.128B(<32 x i32> %11, <32 x i32> %36)
+ %38 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf32.128B(<32 x i32> %10, <32 x i32> %37)
+ %39 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.128B(<32 x i32> %38, <32 x i32> %36)
+ %40 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf32.128B(<32 x i32> %8, <32 x i32> %39)
+ %41 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.128B(<32 x i32> %40, <32 x i32> %36)
+ %42 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf32.128B(<32 x i32> %6, <32 x i32> %41)
+ %43 = tail call <32 x i32> @llvm.hexagon.V6.vmpy.qf32.128B(<32 x i32> %42, <32 x i32> %36)
+ %44 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf32.128B(<32 x i32> %4, <32 x i32> %43)
+ %45 = tail call <32 x i32> @llvm.hexagon.V6.vconv.sf.qf32.128B(<32 x i32> %44)
+ %46 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> zeroinitializer, <32 x i32> %45, <32 x i32> zeroinitializer)
+ %47 = tail call <32 x i32> @llvm.hexagon.V6.vxor.128B(<32 x i32> %46, <32 x i32> %2)
+ %48 = tail call <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1> %33, <32 x i32> %46, <32 x i32> %47)
+ %incdec.ptr14 = getelementptr inbounds <32 x i32>, ptr %optr.1102, i32 1
+ store <32 x i32> %48, ptr %optr.1102, align 4
+ %inc = add nuw nsw i32 %j.0104, 1
+ %exitcond.not = icmp eq i32 %inc, %0
+ br i1 %exitcond.not, label %for.cond.loopexit, label %for.body12
+}
+
+declare i32 @llvm.hexagon.A2.min(i32, i32) #1
+declare <32 x i32> @llvm.hexagon.V6.valignb.128B(<32 x i32>, <32 x i32>, i32) #1
+declare <32 x i32> @llvm.hexagon.V6.vd0.128B() #1
+declare <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32) #1
+declare <32 x i32> @llvm.hexagon.V6.vadd.sf.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vandqrt.128B(<128 x i1>, i32) #1
+declare <128 x i1> @llvm.hexagon.V6.vgtsf.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vxor.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vmux.128B(<128 x i1>, <32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.vandvrt.128B(<32 x i32>, i32) #1
+declare <32 x i32> @llvm.hexagon.V6.vmpy.qf32.sf.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vconv.sf.qf32.128B(<32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vand.128B(<32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.veqw.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vsub.sf.128B(<32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.pred.xor.128B(<128 x i1>, <128 x i1>) #1
+declare <32 x i32> @llvm.hexagon.V6.vmpy.qf32.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vadd.qf32.128B(<32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.pred.or.128B(<128 x i1>, <128 x i1>) #1
+declare <128 x i1> @llvm.hexagon.V6.vgtuw.128B(<32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.vgtw.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vmaxw.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vlalignb.128B(<32 x i32>, <32 x i32>, i32) #1
+declare <128 x i1> @llvm.hexagon.V6.pred.scalar2.128B(i32) #1
+declare <128 x i1> @llvm.hexagon.V6.pred.scalar2v2.128B(i32) #1
+declare void @llvm.hexagon.V6.vS32b.qpred.ai.128B(<128 x i1>, ptr, <32 x i32>) #2
+declare <128 x i1> @llvm.hexagon.V6.veqb.128B(<32 x i32>, <32 x i32>) #1
+declare <128 x i1> @llvm.hexagon.V6.pred.or.n.128B(<128 x i1>, <128 x i1>) #1
+declare void @llvm.hexagon.V6.vS32b.nqpred.ai.128B(<128 x i1>, ptr, <32 x i32>) #2
+
+uselistorder ptr @llvm.hexagon.V6.lvsplatw.128B, { 6, 5, 4, 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vadd.sf.128B, { 4, 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vxor.128B, { 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vmux.128B, { 7, 6, 5, 4, 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vmpy.qf32.sf.128B, { 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vconv.sf.qf32.128B, { 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vmpy.qf32.128B, { 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vadd.qf32.128B, { 3, 2, 1, 0 }
+uselistorder ptr @llvm.hexagon.V6.vmaxw.128B, { 1, 0 }
+
+attributes #0 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-long-calls,-small-data" }
+attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #2 = { nocallback nofree nosync nounwind willreturn memory(write) }
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
index 002ba49d467b0..beb4d421d5e4d 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
@@ -4,7 +4,7 @@
; NOTE: XFAIL until Hexagon HVX IEEEâQFloat isel translation is upstreamed; remove XFAIL when that lands.
; RUN: llc -O2 -march=hexagon -mcpu=hexagonv81 -enable-xqf-gen=true \
; RUN: -hexagon-qfloat-mode=ieee -mattr=+hvxv81,+hvx-length128B \
-; RUN: -debug-only=handle-qfp 2>&1 < %s -o /dev/null | FileCheck %s
+; RUN: -enable-postra-xqf-check -debug-only=handle-qfp 2>&1 < %s -o /dev/null | FileCheck %s
; CHECK: Finding uses of: renamable $v1 = PS_vloadrv_ai %stack.0
; CHECK: Collecting convert instruction with type Hi Op : renamable $v{{[0-9]+}} = V6_vconv_hf_qf32 killed renamable $w0
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-fakereg.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-fakereg.ll
index 70d8778be5a67..486b2b6c07b29 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-fakereg.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-fakereg.ll
@@ -1,7 +1,7 @@
; There should not be any mismatch for xqf with this testcase.
; RUN: llc -O3 -mv81 -mattr=+hvxv81,+hvx-length128b,+hvx-qfloat,+hvx-ieee-fp -enable-xqf-gen=true \
-; RUN: -mtriple=hexagon -hexagon-qfloat-mode=lossy < %s -o - | FileCheck %s
+; RUN: -mtriple=hexagon -hexagon-qfloat-mode=lossy -enable-postra-xqf-check < %s -o - | FileCheck %s
; CHECK-NOT: Mismatch
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
index 5ccedae317acd..d5704fb6e6956 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
@@ -6,7 +6,7 @@
; REQUIRES: asserts
; RUN: llc -O2 -mtriple=hexagon -mattr=+hvxv81,+hvx-length128B \
; RUN: -enable-xqf-gen=true -hexagon-qfloat-mode=lossy \
-; RUN: -debug-only=handle-qfp < %s 2>&1 -o - | FileCheck %s
+; RUN: -debug-only=handle-qfp -enable-postra-xqf-check < %s 2>&1 -o - | FileCheck %s
; CHECK: [HandleConvertToQfCopies] Processing Copy: renamable [[V0:\$v[0-9]+]] = COPY
; CHECK: Inserting new instruction: [[V0]] = V6_vconv_qf32_sf killed renamable [[V0]]
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg3.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg3.ll
new file mode 100644
index 0000000000000..ca17d6c01d0a1
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg3.ll
@@ -0,0 +1,45 @@
+; Test passes if there is no mismatch on a convert instruction
+;
+; UNSUPPORTED: asserts
+
+; REQUIRES: asserts
+; RUN: llc -O2 -mtriple=hexagon -mattr=+hvxv81,+hvx-length128B \
+; RUN: -enable-xqf-gen=true -hexagon-qfloat-mode=lossy \
+; RUN: -debug-only=handle-qfp -enable-postra-xqf-check < %s 2>&1 -o - | FileCheck %s
+
+; CHECK: Mismatch: qf32 type used as sf at operand
+; CHECK-NOT: Def: renamable $v{{[0-9]+}} = V6_vconv_qf32_sf renamable
+
+declare <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32>) #0
+
+define tailcc void @widget(ptr %arg, ptr %arg1, i1 %arg2, i1 %arg3, <32 x i32> %arg4) {
+bb:
+ br label %bb5
+
+bb5: ; preds = %bb7, %bb
+ br i1 %arg2, label %bb6, label %bb7
+
+bb6: ; preds = %bb5
+ %load = load <32 x i32>, ptr %arg, align 128
+ br label %bb7
+
+bb7: ; preds = %bb6, %bb5
+ %phi = phi <32 x i32> [ %load, %bb6 ], [ zeroinitializer, %bb5 ]
+ %call = tail call <64 x i32> @llvm.hexagon.V6.vmpy.sf.hf.acc.128B(<64 x i32> zeroinitializer, <32 x i32> %phi, <32 x i32> zeroinitializer)
+ tail call void (i32, i32, ptr, ...) %arg(i32 0, i32 0, ptr null, ptr null, i32 0, ptr null, ptr null)
+ %call8 = tail call <64 x i32> @llvm.hexagon.V6.vmpy.sf.hf.acc.128B(<64 x i32> %call, <32 x i32> zeroinitializer, <32 x i32> zeroinitializer)
+ %call9 = tail call <64 x i32> @llvm.hexagon.V6.vmpy.sf.hf.acc.128B(<64 x i32> %call8, <32 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, <32 x i32> zeroinitializer)
+ %call10 = tail call <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32> %call9)
+ %call11 = tail call <32 x i32> @llvm.hexagon.V6.vcvt.hf.sf.128B(<32 x i32> zeroinitializer, <32 x i32> %call10)
+ store <32 x i32> %call11, ptr %arg1, align 128
+ br i1 %arg3, label %bb5, label %bb12
+
+bb12: ; preds = %bb12, %bb7
+ store <32 x i32> %arg4, ptr %arg, align 128
+ br label %bb12
+}
+
+declare <64 x i32> @llvm.hexagon.V6.vmpy.sf.hf.acc.128B(<64 x i32>, <32 x i32>, <32 x i32>) #0
+declare <32 x i32> @llvm.hexagon.V6.vcvt.hf.sf.128B(<32 x i32>, <32 x i32>) #0
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-warnings.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-warnings.ll
new file mode 100644
index 0000000000000..16e6c2a9dc75d
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-warnings.ll
@@ -0,0 +1,60 @@
+; Tests for emitted warnings when IEEE type is used as qf and vice-versa
+; post register allocation.
+
+; REQUIRES: asserts
+; RUN: llc --mtriple=hexagon-- -mhvx -mcpu=hexagonv79 -mattr=+hvxv79,+hvx-length128b,+hvx-qfloat \
+; RUN: -enable-xqf-gen=false -enable-postra-xqf-check=true -hexagon-qfloat-mode=ieee \
+; RUN: -verify-machineinstrs 2>&1 < %s -o /dev/null | FileCheck %s
+; RUN: llc --mtriple=hexagon-- -mhvx -mcpu=hexagonv81 -mattr=+hvxv81,+hvx-length128b,+hvx-qfloat \
+; RUN: -enable-xqf-gen=false -enable-postra-xqf-check=true -hexagon-qfloat-mode=ieee \
+; RUN: -verify-machineinstrs 2>&1 < %s -o /dev/null | FileCheck %s
+
+define dso_local inreg <64 x i32> @foo(<32 x i32> noundef %vina, <32 x i32> noundef %vinb) local_unnamed_addr #0{
+;CHECK: Mismatch: hf type used as qf16 at operand 1
+;CHECK-NEXT: Def: renamable [[VREG2:\$v[0-9]+]] = V6_lvsplath
+;CHECK-NEXT: Use: renamable $v{{[0-9]+}} = V6_vadd_qf16_mix killed renamable [[VREG2]]
+;CHECK-NEXT: Mismatch: sf type used as qf32 at operand 1
+;CHECK-NEXT: Def: renamable [[VREG4:\$v[0-9]+]] = V6_lvsplatw
+;CHECK-NEXT: Use: renamable $v{{[0-9]+}} = V6_vadd_qf32_mix killed renamable [[VREG4]]
+;CHECK-NEXT: Mismatch: qf16 type used as hf at operand 2
+;CHECK-NEXT: Def: renamable [[VREG6:\$v[0-9]+]] = V6_vadd_qf16_mix
+;CHECK-NEXT: Use: renamable $w{{[0-9]+}} = V6_vmpy_qf32_hf killed renamable $v{{[0-9]+}}, killed renamable [[VREG6]]
+;CHECK-NEXT: Mismatch: qf32 type used as sf at operand 2
+;CHECK-NEXT: Def: renamable [[VREG7:\$v[0-9]+]] = V6_vadd_qf32_mix
+;CHECK-NEXT: Use: renamable $v{{[0-9]+}} = V6_vsub_qf32_mix killed renamable $v{{[0-9]+}}, renamable [[VREG7]]
+;CHECK: Mismatch: qf32 type used as sf at operand 2
+;CHECK: Def: renamable $v[[R0:[0-9]+]] = V6_vsub_qf32_mix
+;CHECK: Mismatch: qf32 type used as sf at operand 2
+;CHECK: Def: renamable $v[[R1:[0-9]+]] = V6_vsub_qf32
+entry:
+ %0 = tail call <32 x i32> @llvm.hexagon.V6.lvsplath.128B(i32 15360)
+ %1 = tail call <32 x i32> @llvm.hexagon.V6.lvsplath.128B(i32 48128)
+ %2 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 44032)
+ %3 = tail call <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32 56320)
+ %4 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf16.mix.128B(<32 x i32> %0, <32 x i32> %1)
+ %5 = tail call <32 x i32> @llvm.hexagon.V6.vadd.qf32.mix.128B(<32 x i32> %2, <32 x i32> %3)
+ %6 = tail call <64 x i32> @llvm.hexagon.V6.vmpy.qf32.qf16.128B(<32 x i32> %vina, <32 x i32> %4)
+ %7 = tail call <64 x i32> @llvm.hexagon.V6.vmpy.qf32.hf.128B(<32 x i32> %vinb, <32 x i32> %4)
+ %8 = tail call <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32> %6)
+ %9 = tail call <32 x i32> @llvm.hexagon.V6.vsub.qf32.mix.128B(<32 x i32> %8, <32 x i32> %5)
+ %10 = tail call <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32> %7)
+ %11 = tail call <32 x i32> @llvm.hexagon.V6.vsub.qf32.128B(<32 x i32> %10, <32 x i32> %5)
+ %12 = tail call <64 x i32> @llvm.hexagon.V6.vcombine.128B(<32 x i32> %11, <32 x i32> %9)
+ ret <64 x i32> %12
+}
+
+declare <32 x i32> @llvm.hexagon.V6.lvsplath.128B(i32) #1
+declare <32 x i32> @llvm.hexagon.V6.lvsplatw.128B(i32) #1
+declare <32 x i32> @llvm.hexagon.V6.vadd.qf16.mix.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vadd.qf32.mix.128B(<32 x i32>, <32 x i32>) #1
+declare <64 x i32> @llvm.hexagon.V6.vmpy.qf32.qf16.128B(<32 x i32>, <32 x i32>) #1
+declare <64 x i32> @llvm.hexagon.V6.vmpy.qf32.hf.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vsub.qf32.mix.128B(<32 x i32>, <32 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32>) #1
+declare <32 x i32> @llvm.hexagon.V6.vsub.qf32.128B(<32 x i32>, <32 x i32>) #1
+declare <64 x i32> @llvm.hexagon.V6.vcombine.128B(<32 x i32>, <32 x i32>) #1
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { mustprogress nofree nosync nounwind willreturn memory(none) "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-long-calls" "unsafe-fp-math"="true" }
+attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
More information about the llvm-commits
mailing list