@@ -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