Skip to content

Commit 0fb3d42

Browse files
authored
[AArch64][GlobalISel] Refactor BITCAST Legalization (#80505)
Ensure BITCAST is only legal for types with the same amount of bits. Enable BITCAST to work with non-legal vector types as well.
1 parent 654e65d commit 0fb3d42

File tree

5 files changed

+307
-178
lines changed

5 files changed

+307
-178
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ class LegalizerHelper {
338338
unsigned TypeIdx,
339339
LLT NarrowTy);
340340

341+
// Fewer Elements for bitcast, ensuring that the size of the Src and Dst
342+
// registers will be the same
343+
LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx,
344+
LLT NarrowTy);
345+
341346
LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx,
342347
LLT NarrowTy);
343348

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4677,11 +4677,44 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
46774677
return fewerElementsVectorShuffle(MI, TypeIdx, NarrowTy);
46784678
case G_FPOWI:
46794679
return fewerElementsVectorMultiEltType(GMI, NumElts, {2 /*pow*/});
4680+
case G_BITCAST:
4681+
return fewerElementsBitcast(MI, TypeIdx, NarrowTy);
46804682
default:
46814683
return UnableToLegalize;
46824684
}
46834685
}
46844686

4687+
LegalizerHelper::LegalizeResult
4688+
LegalizerHelper::fewerElementsBitcast(MachineInstr &MI, unsigned int TypeIdx,
4689+
LLT NarrowTy) {
4690+
assert(MI.getOpcode() == TargetOpcode::G_BITCAST &&
4691+
"Not a bitcast operation");
4692+
4693+
if (TypeIdx != 0)
4694+
return UnableToLegalize;
4695+
4696+
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
4697+
4698+
unsigned SrcScalSize = SrcTy.getScalarSizeInBits();
4699+
LLT SrcNarrowTy =
4700+
LLT::fixed_vector(NarrowTy.getSizeInBits() / SrcScalSize, SrcScalSize);
4701+
4702+
// Split the Src and Dst Reg into smaller registers
4703+
SmallVector<Register> SrcVRegs, BitcastVRegs;
4704+
if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
4705+
return UnableToLegalize;
4706+
4707+
// Build new smaller bitcast instructions
4708+
// Not supporting Leftover types for now but will have to
4709+
for (unsigned i = 0; i < SrcVRegs.size(); i++)
4710+
BitcastVRegs.push_back(
4711+
MIRBuilder.buildBitcast(NarrowTy, SrcVRegs[i]).getReg(0));
4712+
4713+
MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
4714+
MI.eraseFromParent();
4715+
return Legalized;
4716+
}
4717+
46854718
LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorShuffle(
46864719
MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) {
46874720
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
@@ -5366,6 +5399,27 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
53665399
Observer.changedInstr(MI);
53675400
return Legalized;
53685401
}
5402+
case TargetOpcode::G_BITCAST: {
5403+
if (TypeIdx != 0)
5404+
return UnableToLegalize;
5405+
5406+
LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
5407+
LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
5408+
5409+
unsigned coefficient = SrcTy.getNumElements() * MoreTy.getNumElements();
5410+
if (coefficient % DstTy.getNumElements() != 0)
5411+
return UnableToLegalize;
5412+
5413+
coefficient = coefficient / DstTy.getNumElements();
5414+
5415+
LLT NewTy = SrcTy.changeElementCount(
5416+
ElementCount::get(coefficient, MoreTy.isScalable()));
5417+
Observer.changingInstr(MI);
5418+
moreElementsVectorSrc(MI, NewTy, 1);
5419+
moreElementsVectorDst(MI, MoreTy, 0);
5420+
Observer.changedInstr(MI);
5421+
return Legalized;
5422+
}
53695423
default:
53705424
return UnableToLegalize;
53715425
}

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -740,12 +740,15 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
740740
// Casts for 32 and 64-bit width type are just copies.
741741
// Same for 128-bit width type, except they are on the FPR bank.
742742
getActionDefinitionsBuilder(G_BITCAST)
743-
// FIXME: This is wrong since G_BITCAST is not allowed to change the
744-
// number of bits but it's what the previous code described and fixing
745-
// it breaks tests.
746-
.legalForCartesianProduct({s8, s16, s32, s64, s128, v16s8, v8s8, v4s8,
747-
v8s16, v4s16, v2s16, v4s32, v2s32, v2s64,
748-
v2p0});
743+
// Keeping 32-bit instructions legal to prevent regression in some tests
744+
.legalForCartesianProduct({s32, v2s16, v4s8})
745+
.legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
746+
.legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
747+
.moreElementsToNextPow2(0)
748+
.clampNumElements(0, v8s8, v16s8)
749+
.clampNumElements(0, v4s16, v8s16)
750+
.clampNumElements(0, v2s32, v4s32)
751+
.lower();
749752

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

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@
127127
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
128128
#
129129
# DEBUG-NEXT: G_BITCAST (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
130-
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
131-
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
130+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
131+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
132132
#
133133
# DEBUG-NEXT: G_FREEZE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
134134
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}

0 commit comments

Comments
 (0)