[llvm] [Hexagon] Add XQFloat post-RA compliance checker (PR #207082)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 14:49:59 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: Fateme Hosseini (fhossein-quic)
<details>
<summary>Changes</summary>
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.
---
Patch is 34.53 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207082.diff
8 Files Affected:
- (modified) llvm/include/llvm/CodeGen/RDFGraph.h (+2)
- (modified) llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp (+164-74)
- (added) llvm/test/CodeGen/Hexagon/autohvx/xqf-multi-conv.ll (+133)
- (modified) llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll (+1-1)
- (modified) llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-fakereg.ll (+1-1)
- (modified) llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll (+1-1)
- (added) llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg3.ll (+45)
- (added) llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-warnings.ll (+60)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/RDFGraph.h b/llvm/include/llvm/CodeGen/RDFGraph.h
index 27b5795b8ed2d..bd1bcc87b0db6 100644
--- a/llvm/include/llvm/CodeGen/RDFGraph.h
+++ b/llvm/include/llvm/CodeGen/RDFGraph.h
@@ -358,6 +358,8 @@ template <typename T> struct NodeAddr {
return !operator==(NA);
}
+ bool operator<(const NodeAddr<T> &NA) const { return Id < NA.Id; }
+
T Addr = nullptr;
NodeId Id = 0;
};
diff --git a/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp b/llvm/lib/Target/Hexagon/HexagonPostRAHandleQFP.cpp
index 06ee6e5fa0414..09711a16a9c3c 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,143 @@ 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);
+
+ 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 +1031,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 +1067,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 +1151,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 +1173,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 +1484,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 +1511,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 +1537,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 +1815,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 = ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/207082
More information about the llvm-commits
mailing list