diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -269,7 +269,7 @@ if (Opcode == TargetOpcode::G_ANYEXT) { // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF - if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) + if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) return false; LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;); Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {}); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -727,19 +727,36 @@ default: return UnableToLegalize; case TargetOpcode::G_IMPLICIT_DEF: { - // FIXME: add support for when SizeOp0 isn't an exact multiple of - // NarrowSize. - if (SizeOp0 % NarrowSize != 0) - return UnableToLegalize; + Register DstReg = MI.getOperand(0).getReg(); + LLT DstTy = MRI.getType(DstReg); + + // If SizeOp0 is not an exact multiple of NarrowSize, emit + // G_ANYEXT(G_IMPLICIT_DEF). Cast result to vector if needed. + // FIXME: Although this would also be legal for the general case, it causes + // a lot of regressions in the emitted code (superfluous COPYs, artifact + // combines not being hit). This seems to be a problem related to the + // artifact combiner. + if (SizeOp0 % NarrowSize != 0) { + Register ImplicitReg = MIRBuilder.buildUndef(NarrowTy).getReg(0); + Register AnyExtReg = DstReg; + if (DstTy.isVector()) + AnyExtReg = MRI.createGenericVirtualRegister(LLT::scalar(SizeOp0)); + + MIRBuilder.buildAnyExt(AnyExtReg, ImplicitReg); + if (DstTy.isVector()) + MIRBuilder.buildBitcast(DstReg, AnyExtReg); + + MI.removeFromBundle(); + return Legalized; + } + int NumParts = SizeOp0 / NarrowSize; SmallVector DstRegs; for (int i = 0; i < NumParts; ++i) - DstRegs.push_back( - MIRBuilder.buildUndef(NarrowTy).getReg(0)); + DstRegs.push_back(MIRBuilder.buildUndef(NarrowTy).getReg(0)); - Register DstReg = MI.getOperand(0).getReg(); - if(MRI.getType(DstReg).isVector()) + if (DstTy.isVector()) MIRBuilder.buildBuildVector(DstReg, DstRegs); else MIRBuilder.buildMerge(DstReg, DstRegs); diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp --- a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp @@ -2516,4 +2516,61 @@ EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } +// Test lowering of G_BSWAP +TEST_F(GISelMITest, NarrowImplicitDef) { + setUp(); + if (!TM) + return; + + DefineLegalizerInfo(A, {}); + + // Make sure that G_IMPLICIT_DEF can be narrowed if the original size is not a + // multiple of narrow size + LLT S32{LLT::scalar(32)}; + LLT S48{LLT::scalar(48)}; + LLT S64{LLT::scalar(64)}; + LLT V2S64{{LLT::vector(2, 64)}}; + + auto Implicit1 = B.buildUndef(S64); + auto Implicit2 = B.buildUndef(S64); + auto Implicit3 = B.buildUndef(V2S64); + auto Implicit4 = B.buildUndef(V2S64); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + // Perform Legalization + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.narrowScalar(*Implicit1, 0, S48)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.narrowScalar(*Implicit2, 0, S32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.narrowScalar(*Implicit3, 0, S48)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.narrowScalar(*Implicit4, 0, S32)); + + const auto *CheckStr = R"( + CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF + CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[DEF]] + + CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]]:_(s32), [[DEF1]] + + CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT [[DEF]] + CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[ANYEXT]] + + CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[DEF3:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + CHECK: [[BV:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[DEF]]:_(s32), [[DEF1]]:_(s32), [[DEF2]]:_(s32), [[DEF3]]:_(s32) + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + } // namespace