Skip to content

[AArch64][GlobalISel] Refactor BITCAST Legalization #80505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,11 @@ class LegalizerHelper {
unsigned TypeIdx,
LLT NarrowTy);

// Fewer Elements for bitcast, ensuring that the size of the Src and Dst
// registers will be the same
LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx,
LLT NarrowTy);

LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx,
LLT NarrowTy);

Expand Down
54 changes: 54 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4677,11 +4677,44 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
return fewerElementsVectorShuffle(MI, TypeIdx, NarrowTy);
case G_FPOWI:
return fewerElementsVectorMultiEltType(GMI, NumElts, {2 /*pow*/});
case G_BITCAST:
return fewerElementsBitcast(MI, TypeIdx, NarrowTy);
default:
return UnableToLegalize;
}
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsBitcast(MachineInstr &MI, unsigned int TypeIdx,
LLT NarrowTy) {
assert(MI.getOpcode() == TargetOpcode::G_BITCAST &&
"Not a bitcast operation");

if (TypeIdx != 0)
return UnableToLegalize;

auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();

unsigned SrcScalSize = SrcTy.getScalarSizeInBits();
LLT SrcNarrowTy =
LLT::fixed_vector(NarrowTy.getSizeInBits() / SrcScalSize, SrcScalSize);

// Split the Src and Dst Reg into smaller registers
SmallVector<Register> SrcVRegs, BitcastVRegs;
if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
return UnableToLegalize;

// Build new smaller bitcast instructions
// Not supporting Leftover types for now but will have to
for (unsigned i = 0; i < SrcVRegs.size(); i++)
BitcastVRegs.push_back(
MIRBuilder.buildBitcast(NarrowTy, SrcVRegs[i]).getReg(0));

MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
MI.eraseFromParent();
return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorShuffle(
MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) {
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
Expand Down Expand Up @@ -5366,6 +5399,27 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_BITCAST: {
if (TypeIdx != 0)
return UnableToLegalize;

LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
LLT DstTy = MRI.getType(MI.getOperand(0).getReg());

unsigned coefficient = SrcTy.getNumElements() * MoreTy.getNumElements();
if (coefficient % DstTy.getNumElements() != 0)
return UnableToLegalize;

coefficient = coefficient / DstTy.getNumElements();

LLT NewTy = SrcTy.changeElementCount(
ElementCount::get(coefficient, MoreTy.isScalable()));
Observer.changingInstr(MI);
moreElementsVectorSrc(MI, NewTy, 1);
moreElementsVectorDst(MI, MoreTy, 0);
Observer.changedInstr(MI);
return Legalized;
}
default:
return UnableToLegalize;
}
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,12 +740,15 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
// Casts for 32 and 64-bit width type are just copies.
// Same for 128-bit width type, except they are on the FPR bank.
getActionDefinitionsBuilder(G_BITCAST)
// FIXME: This is wrong since G_BITCAST is not allowed to change the
// number of bits but it's what the previous code described and fixing
// it breaks tests.
.legalForCartesianProduct({s8, s16, s32, s64, s128, v16s8, v8s8, v4s8,
v8s16, v4s16, v2s16, v4s32, v2s32, v2s64,
v2p0});
// Keeping 32-bit instructions legal to prevent regression in some tests
.legalForCartesianProduct({s32, v2s16, v4s8})
.legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
.legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
.moreElementsToNextPow2(0)
.clampNumElements(0, v8s8, v16s8)
.clampNumElements(0, v4s16, v8s16)
.clampNumElements(0, v2s32, v4s32)
.lower();

getActionDefinitionsBuilder(G_VASTART).legalFor({p0});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
#
# DEBUG-NEXT: G_BITCAST (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
#
# DEBUG-NEXT: G_FREEZE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
Expand Down
Loading