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 @@ -1390,11 +1390,12 @@ if (!DstTy.isScalar()) return UnableToLegalize; - if (WideTy.getSizeInBits() == SrcTy.getSizeInBits()) { + if (WideTy.getSizeInBits() >= SrcTy.getSizeInBits()) { if (SrcTy.isPointer()) { const DataLayout &DL = MIRBuilder.getDataLayout(); if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) { - LLVM_DEBUG(dbgs() << "Not casting non-integral address space integer\n"); + LLVM_DEBUG( + dbgs() << "Not casting non-integral address space integer\n"); return UnableToLegalize; } @@ -1402,6 +1403,14 @@ SrcReg = MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0); } + // Widen SrcTy to WideTy. This does not affect the result, but since the + // user requested this size, it is probably better handled than SrcTy and + // should reduce the total number of legalization artifacts + if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) { + SrcTy = WideTy; + SrcReg = MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0); + } + // Theres no unmerge type to target. Directly extract the bits from the // source type unsigned DstSize = DstTy.getSizeInBits(); @@ -1417,10 +1426,6 @@ return Legalized; } - // TODO - if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) - return UnableToLegalize; - // Extend the source to a wider type. LLT LCMTy = getLCMType(SrcTy, WideTy); diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-unmerge-values.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-unmerge-values.mir --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-unmerge-values.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-unmerge-values.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple=amdgcn-- -O0 -run-pass=legalizer -global-isel-abort=0 -o - %s | FileCheck %s +# RUN: llc -mtriple=amdgcn-- -O0 -run-pass=legalizer -o - %s | FileCheck %s --- name: test_unmerge_s32_s64 @@ -694,14 +694,21 @@ liveins: $vgpr0 ; CHECK-LABEL: name: test_unmerge_s1_s3 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s3) = G_TRUNC [[COPY]](s32) - ; CHECK: [[UV:%[0-9]+]]:_(s1), [[UV1:%[0-9]+]]:_(s1), [[UV2:%[0-9]+]]:_(s1) = G_UNMERGE_VALUES [[TRUNC]](s3) - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UV]](s1) - ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[UV1]](s1) - ; CHECK: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[UV2]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) - ; CHECK: $vgpr1 = COPY [[ANYEXT1]](s32) - ; CHECK: $vgpr2 = COPY [[ANYEXT2]](s32) + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]] + ; CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32) + ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]] + ; CHECK: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[C2]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[LSHR]](s32) + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[LSHR1]](s32) + ; CHECK: $vgpr0 = COPY [[COPY3]](s32) + ; CHECK: $vgpr1 = COPY [[COPY4]](s32) + ; CHECK: $vgpr2 = COPY [[COPY5]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s3) = G_TRUNC %0 %2:_(s1), %3:_(s1), %4:_(s1) = G_UNMERGE_VALUES %1 @@ -720,24 +727,51 @@ liveins: $vgpr0 ; CHECK-LABEL: name: test_unmerge_s1_s8 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) - ; CHECK: [[UV:%[0-9]+]]:_(s1), [[UV1:%[0-9]+]]:_(s1), [[UV2:%[0-9]+]]:_(s1), [[UV3:%[0-9]+]]:_(s1), [[UV4:%[0-9]+]]:_(s1), [[UV5:%[0-9]+]]:_(s1), [[UV6:%[0-9]+]]:_(s1), [[UV7:%[0-9]+]]:_(s1) = G_UNMERGE_VALUES [[TRUNC]](s8) - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UV]](s1) - ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[UV1]](s1) - ; CHECK: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[UV2]](s1) - ; CHECK: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[UV3]](s1) - ; CHECK: [[ANYEXT4:%[0-9]+]]:_(s32) = G_ANYEXT [[UV4]](s1) - ; CHECK: [[ANYEXT5:%[0-9]+]]:_(s32) = G_ANYEXT [[UV5]](s1) - ; CHECK: [[ANYEXT6:%[0-9]+]]:_(s32) = G_ANYEXT [[UV6]](s1) - ; CHECK: [[ANYEXT7:%[0-9]+]]:_(s32) = G_ANYEXT [[UV7]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) - ; CHECK: $vgpr1 = COPY [[ANYEXT1]](s32) - ; CHECK: $vgpr2 = COPY [[ANYEXT2]](s32) - ; CHECK: $vgpr3 = COPY [[ANYEXT3]](s32) - ; CHECK: $vgpr4 = COPY [[ANYEXT4]](s32) - ; CHECK: $vgpr5 = COPY [[ANYEXT5]](s32) - ; CHECK: $vgpr6 = COPY [[ANYEXT6]](s32) - ; CHECK: $vgpr7 = COPY [[ANYEXT7]](s32) + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]] + ; CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32) + ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]] + ; CHECK: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[C2]](s32) + ; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; CHECK: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[C3]](s32) + ; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND3:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C1]] + ; CHECK: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[AND3]], [[C4]](s32) + ; CHECK: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND4:%[0-9]+]]:_(s32) = G_AND [[COPY5]], [[C1]] + ; CHECK: [[LSHR4:%[0-9]+]]:_(s32) = G_LSHR [[AND4]], [[C5]](s32) + ; CHECK: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 6 + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND5:%[0-9]+]]:_(s32) = G_AND [[COPY6]], [[C1]] + ; CHECK: [[LSHR5:%[0-9]+]]:_(s32) = G_LSHR [[AND5]], [[C6]](s32) + ; CHECK: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 7 + ; CHECK: [[COPY7:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[AND6:%[0-9]+]]:_(s32) = G_AND [[COPY7]], [[C1]] + ; CHECK: [[LSHR6:%[0-9]+]]:_(s32) = G_LSHR [[AND6]], [[C7]](s32) + ; CHECK: [[COPY8:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; CHECK: [[COPY9:%[0-9]+]]:_(s32) = COPY [[LSHR]](s32) + ; CHECK: [[COPY10:%[0-9]+]]:_(s32) = COPY [[LSHR1]](s32) + ; CHECK: [[COPY11:%[0-9]+]]:_(s32) = COPY [[LSHR2]](s32) + ; CHECK: [[COPY12:%[0-9]+]]:_(s32) = COPY [[LSHR3]](s32) + ; CHECK: [[COPY13:%[0-9]+]]:_(s32) = COPY [[LSHR4]](s32) + ; CHECK: [[COPY14:%[0-9]+]]:_(s32) = COPY [[LSHR5]](s32) + ; CHECK: [[COPY15:%[0-9]+]]:_(s32) = COPY [[LSHR6]](s32) + ; CHECK: $vgpr0 = COPY [[COPY8]](s32) + ; CHECK: $vgpr1 = COPY [[COPY9]](s32) + ; CHECK: $vgpr2 = COPY [[COPY10]](s32) + ; CHECK: $vgpr3 = COPY [[COPY11]](s32) + ; CHECK: $vgpr4 = COPY [[COPY12]](s32) + ; CHECK: $vgpr5 = COPY [[COPY13]](s32) + ; CHECK: $vgpr6 = COPY [[COPY14]](s32) + ; CHECK: $vgpr7 = COPY [[COPY15]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s8) = G_TRUNC %0 %2:_(s1), %3:_(s1), %4:_(s1), %5:_(s1), %6:_(s1), %7:_(s1), %8:_(s1), %9:_(s1) = G_UNMERGE_VALUES %1 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,53 @@ EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } +// Test widening of G_UNMERGE_VALUES +TEST_F(GISelMITest, WidenUnmerge) { + setUp(); + if (!TM) + return; + + DefineLegalizerInfo(A, {}); + + // Check that widening G_UNMERGE_VALUES to a larger type than the source type + // works as expected + LLT P0{LLT::pointer(0, 64)}; + LLT S32{LLT::scalar(32)}; + LLT S96{LLT::scalar(96)}; + + auto IntToPtr = B.buildIntToPtr(P0, Copies[0]); + auto UnmergePtr = B.buildUnmerge(S32, IntToPtr); + auto UnmergeScalar = B.buildUnmerge(S32, Copies[0]); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + // Perform Legalization + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.widenScalar(*UnmergePtr, 0, S96)); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.widenScalar(*UnmergeScalar, 0, S96)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]] + CHECK: [[INT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR]] + CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[INT]] + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]] + CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32 + CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]] + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]] + CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY]] + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]] + CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32 + CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]] + CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]] + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + } // namespace