[llvm] [AArch64][GlobalISel] Improve lowering of vector fp16 fptrunc and fpext (PR #163398)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 28 01:17:28 PDT 2025
================
@@ -133,6 +137,97 @@ bool isZeroExtended(Register R, MachineRegisterInfo &MRI) {
return MRI.getVRegDef(R)->getOpcode() == TargetOpcode::G_ZEXT;
}
+// This patten aims to match the following shape to avoid extra mov instructions
+// G_BUILD_VECTOR(
+// G_UNMERGE_VALUES(src, 0)
+// G_UNMERGE_VALUES(src, 1)
+// G_IMPLICIT_DEF
+// G_IMPLICIT_DEF
+// )
+// ->
+// G_CONCAT_VECTORS(
+// G_BUILD_VECTOR(
+// G_IMPLICIT_DEF
+// G_IMPLICIT_DEF
+// )
+// src
+// )
+bool matchCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
+ SmallVectorImpl<Register> &UnmergeSrc,
+ SmallVectorImpl<Register> &UndefinedValues) {
+ assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
+
+ UndefinedValues.clear();
+ UnmergeSrc.clear();
+
+ std::set<int> KnownRegs;
+
+ for (auto Use : MI.all_uses()) {
+ auto *Def = getDefIgnoringCopies(Use.getReg(), MRI);
+
+ if (!Def) {
+ UndefinedValues.clear();
+ UnmergeSrc.clear();
+ return false;
+ }
+
+ auto Opcode = Def->getOpcode();
+
+ switch (Opcode) {
+ default:
+ return false;
+ case TargetOpcode::G_IMPLICIT_DEF:
+ UndefinedValues.push_back(Use.getReg());
+ break;
+ case TargetOpcode::G_UNMERGE_VALUES:
+ // We only want to match G_UNMERGE_VALUES <2 x Ty>
+ // s16 is troublesome as <2 x s16> is generally not legal
+ if (Def->getNumDefs() != 2 ||
+ MRI.getType(Use.getReg()) == LLT::scalar(16)) {
+ UndefinedValues.clear();
+ UnmergeSrc.clear();
+ return false;
+ }
+
+ // Only track unique sources for the G_UNMERGE_VALUES
+ if (KnownRegs.find(Def->getOperand(2).getReg().id()) != KnownRegs.end())
+ continue;
+
+ KnownRegs.insert(Def->getOperand(2).getReg().id());
+ UnmergeSrc.push_back(Def->getOperand(2).getReg());
+
+ break;
+ }
+ }
+
+ // Only want to match patterns that pad two values with two undefined values
+ if (!(UndefinedValues.size() == 2 && UnmergeSrc.size() == 1)) {
+ UndefinedValues.clear();
+ UnmergeSrc.clear();
+ return false;
+ }
+
+ return true;
+}
+
+void applyCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
+ MachineIRBuilder &B,
+ SmallVectorImpl<Register> &UnmergeSrc,
+ SmallVectorImpl<Register> &UndefinedValues) {
+ assert(UnmergeSrc.size() == 1 && "Expected there to be one G_UNMERGE_VALUES");
+ B.setInstrAndDebugLoc(MI);
+
+ auto UndefVecLLT = LLT::fixed_vector(
+ UndefinedValues.size(),
+ LLT::scalar(MRI.getType(UnmergeSrc[0]).getScalarSizeInBits()));
+ Register UndefVec = MRI.createGenericVirtualRegister(UndefVecLLT);
+
+ B.buildBuildVector(UndefVec, UndefinedValues);
+ B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc[0], UndefVec});
----------------
davemgreen wrote:
Something like
```
auto Undef = B.buildUndef(MRI.getType(UnmergeSrc[0]));
B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc[0], Undef});
```
It should only need to pass one UnmergeSrc too I suspect.
https://github.com/llvm/llvm-project/pull/163398
More information about the llvm-commits
mailing list