Skip to content

Commit 2088a6e

Browse files
committed
[Z80] Fold constant non power of two funnel shifts and avoid extra split shifts
1 parent 3b0bf74 commit 2088a6e

1 file changed

Lines changed: 89 additions & 5 deletions

File tree

llvm/lib/Target/Z80/GISel/Z80LegalizerInfo.cpp

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ Z80LegalizerInfo::Z80LegalizerInfo(const Z80Subtarget &STI,
359359
getActionDefinitionsBuilder(G_FCMP)
360360
.customForCartesianProduct({s1}, {s32, s64});
361361

362+
getActionDefinitionsBuilder(G_IS_FPCLASS)
363+
.lowerForCartesianProduct({s1}, {s32, s64});
364+
362365
getActionDefinitionsBuilder(G_BRCOND)
363366
.legalFor({s1});
364367

@@ -924,13 +927,94 @@ Z80LegalizerInfo::legalizeFunnelShift(LegalizerHelper &Helper,
924927

925928
LLT Ty = MRI.getType(DstReg);
926929
unsigned BW = Ty.getSizeInBits();
930+
LLT ShTy = MRI.getType(AmtReg);
927931
// Amt & (BW - 1) is only equivalent to modulo when
928-
// bw is a power of two. for i24/i48, defer to the generic lowering path so
929-
// shift amounts are reduced correctly
932+
// bw is a power of two
930933
if ((BW & (BW - 1)) != 0) {
931-
if (Opc == G_ROTR || Opc == G_ROTL)
932-
return Helper.lowerRotate(MI);
933-
return Helper.lowerFunnelShift(MI);
934+
Register ShAmtReg;
935+
if (auto AmtC = getIConstantVRegValWithLookThrough(AmtReg, MRI)) {
936+
ShAmtReg = MIRBuilder.buildConstant(ShTy, AmtC->Value.urem(BW)).getReg(0);
937+
} else {
938+
MachineInstr *AmtDef = MRI.getVRegDef(AmtReg);
939+
if (!AmtDef) {
940+
if (Opc == G_ROTR || Opc == G_ROTL)
941+
return Helper.lowerRotate(MI);
942+
return Helper.lowerFunnelShift(MI);
943+
}
944+
unsigned AmtOpc = AmtDef->getOpcode();
945+
if (AmtOpc != G_UREM && AmtOpc != G_SREM) {
946+
if (Opc == G_ROTR || Opc == G_ROTL)
947+
return Helper.lowerRotate(MI);
948+
return Helper.lowerFunnelShift(MI);
949+
}
950+
951+
auto DivC = getIConstantVRegValWithLookThrough(AmtDef->getOperand(2).getReg(),
952+
MRI);
953+
if (!DivC || DivC->Value != BW) {
954+
if (Opc == G_ROTR || Opc == G_ROTL)
955+
return Helper.lowerRotate(MI);
956+
return Helper.lowerFunnelShift(MI);
957+
}
958+
959+
if (AmtOpc == G_UREM) {
960+
ShAmtReg = AmtReg;
961+
} else {
962+
auto Zero = MIRBuilder.buildConstant(ShTy, 0);
963+
auto BWConst = MIRBuilder.buildConstant(ShTy, BW);
964+
auto IsNeg =
965+
MIRBuilder.buildICmp(CmpInst::ICMP_SLT, LLT::scalar(1), AmtReg, Zero);
966+
auto AddBW = MIRBuilder.buildAdd(ShTy, AmtReg, BWConst);
967+
ShAmtReg = MIRBuilder.buildSelect(ShTy, IsNeg, AddBW, AmtReg).getReg(0);
968+
}
969+
}
970+
971+
bool IsFSHL = Opc == G_FSHL || Opc == G_ROTL;
972+
Register XReg = MI.getOperand(1).getReg();
973+
Register YReg = MI.getOperand(MI.getNumExplicitOperands() - 2).getReg();
974+
975+
if (auto ShAmtC = getIConstantVRegValWithLookThrough(ShAmtReg, MRI)) {
976+
unsigned C = ShAmtC->Value.urem(BW);
977+
if (C == 0) {
978+
MIRBuilder.buildCopy(DstReg, IsFSHL ? XReg : YReg);
979+
MI.eraseFromParent();
980+
return LegalizerHelper::Legalized;
981+
}
982+
983+
auto ShC = MIRBuilder.buildConstant(ShTy, C);
984+
auto InvShC = MIRBuilder.buildConstant(ShTy, BW - C);
985+
Register ShXReg, ShYReg;
986+
if (IsFSHL) {
987+
ShXReg = MIRBuilder.buildShl(Ty, XReg, ShC).getReg(0);
988+
ShYReg = MIRBuilder.buildLShr(Ty, YReg, InvShC).getReg(0);
989+
} else {
990+
ShXReg = MIRBuilder.buildShl(Ty, XReg, InvShC).getReg(0);
991+
ShYReg = MIRBuilder.buildLShr(Ty, YReg, ShC).getReg(0);
992+
}
993+
MIRBuilder.buildOr(DstReg, ShXReg, ShYReg);
994+
MI.eraseFromParent();
995+
return LegalizerHelper::Legalized;
996+
}
997+
998+
// fshl: (X << C) | (Y >> 1 >> ((BW - 1) - C))
999+
// fshr: (X << 1 << ((BW - 1) - C)) | (Y >> C)
1000+
auto BWMinus1 = MIRBuilder.buildConstant(ShTy, BW - 1);
1001+
auto InvShAmtReg = MIRBuilder.buildSub(ShTy, BWMinus1, ShAmtReg);
1002+
auto One = MIRBuilder.buildConstant(ShTy, 1);
1003+
1004+
Register ShXReg, ShYReg;
1005+
if (IsFSHL) {
1006+
ShXReg = MIRBuilder.buildShl(Ty, XReg, ShAmtReg).getReg(0);
1007+
auto ShY1Reg = MIRBuilder.buildLShr(Ty, YReg, One);
1008+
ShYReg = MIRBuilder.buildLShr(Ty, ShY1Reg, InvShAmtReg).getReg(0);
1009+
} else {
1010+
auto ShX1Reg = MIRBuilder.buildShl(Ty, XReg, One);
1011+
ShXReg = MIRBuilder.buildShl(Ty, ShX1Reg, InvShAmtReg).getReg(0);
1012+
ShYReg = MIRBuilder.buildLShr(Ty, YReg, ShAmtReg).getReg(0);
1013+
}
1014+
1015+
MIRBuilder.buildOr(DstReg, ShXReg, ShYReg);
1016+
MI.eraseFromParent();
1017+
return LegalizerHelper::Legalized;
9341018
}
9351019
if (Ty == LLT::scalar(8))
9361020
if (auto Amt = getIConstantVRegValWithLookThrough(AmtReg, MRI))

0 commit comments

Comments
 (0)