[llvm] r340429 - [GISel]: Add legalization support for widening bit counting operations
Aditya Nandakumar via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 22 10:59:18 PDT 2018
Author: aditya_nandakumar
Date: Wed Aug 22 10:59:18 2018
New Revision: 340429
URL: http://llvm.org/viewvc/llvm-project?rev=340429&view=rev
Log:
[GISel]: Add legalization support for widening bit counting operations
https://reviews.llvm.org/D51053
Added legalization for WidenScalar of various bitcounting opcodes.
Reviewed by arsenm.
Modified:
llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
Modified: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp?rev=340429&r1=340428&r2=340429&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp Wed Aug 22 10:59:18 2018
@@ -619,6 +619,42 @@ LegalizerHelper::widenScalar(MachineInst
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
+ case TargetOpcode::G_CTTZ:
+ case TargetOpcode::G_CTTZ_ZERO_UNDEF:
+ case TargetOpcode::G_CTLZ:
+ case TargetOpcode::G_CTLZ_ZERO_UNDEF:
+ case TargetOpcode::G_CTPOP: {
+ // First ZEXT the input.
+ auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
+ LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
+ if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
+ // The count is the same in the larger type except if the original
+ // value was zero. This can be handled by setting the bit just off
+ // the top of the original type.
+ auto TopBit =
+ APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
+ MIBSrc = MIRBuilder.buildInstr(
+ TargetOpcode::G_OR, WideTy, MIBSrc,
+ MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue()));
+ }
+ // Perform the operation at the larger size.
+ auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), WideTy, MIBSrc);
+ // This is already the correct result for CTPOP and CTTZs
+ if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
+ MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
+ // The correct result is NewOp - (Difference in widety and current ty).
+ unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
+ MIBNewOp =
+ MIRBuilder.buildInstr(TargetOpcode::G_SUB, WideTy, MIBNewOp,
+ MIRBuilder.buildConstant(WideTy, SizeDiff));
+ }
+ auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
+ // Make the original instruction a trunc now, and update it's source.
+ MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
+ MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
+ MIRBuilder.recordInsertion(&MI);
+ return Legalized;
+ }
case TargetOpcode::G_ADD:
case TargetOpcode::G_AND:
Modified: llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp?rev=340429&r1=340428&r2=340429&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp Wed Aug 22 10:59:18 2018
@@ -185,4 +185,161 @@ TEST_F(LegalizerHelperTest, LowerBitCoun
// Check
ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
}
+
+// CTLZ widening.
+TEST_F(LegalizerHelperTest, WidenBitCountingCTLZ) {
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(A,
+ { getActionDefinitionsBuilder(G_CTLZ).legalFor({s16}); });
+ // Build
+ // Trunc it to s8.
+ LLT s8{LLT::scalar(8)};
+ LLT s16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+ auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc);
+ AInfo Info(MF->getSubtarget());
+ LegalizerHelper Helper(*MF, Info);
+ ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ, 0, s16) ==
+ LegalizerHelper::LegalizeResult::Legalized);
+
+ auto CheckStr = R"(
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+ CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+ CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
+ CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
+ CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
+ )";
+
+ // Check
+ ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
+
+// CTLZ_ZERO_UNDEF widening.
+TEST_F(LegalizerHelperTest, WidenBitCountingCTLZZeroUndef) {
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(
+ A, { getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({s16}); });
+ // Build
+ // Trunc it to s8.
+ LLT s8{LLT::scalar(8)};
+ LLT s16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+ auto MIBCTLZ_ZU = B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, s8, MIBTrunc);
+ AInfo Info(MF->getSubtarget());
+ LegalizerHelper Helper(*MF, Info);
+ ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 0, s16) ==
+ LegalizerHelper::LegalizeResult::Legalized);
+
+ auto CheckStr = R"(
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+ CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+ CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
+ CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
+ CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
+ )";
+
+ // Check
+ ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
+
+// CTPOP widening.
+TEST_F(LegalizerHelperTest, WidenBitCountingCTPOP) {
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(
+ A, { getActionDefinitionsBuilder(G_CTPOP).legalFor({s16}); });
+ // Build
+ // Trunc it to s8.
+ LLT s8{LLT::scalar(8)};
+ LLT s16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+ auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, s8, MIBTrunc);
+ AInfo Info(MF->getSubtarget());
+ LegalizerHelper Helper(*MF, Info);
+ ASSERT_TRUE(Helper.widenScalar(*MIBCTPOP, 0, s16) ==
+ LegalizerHelper::LegalizeResult::Legalized);
+
+ auto CheckStr = R"(
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+ CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+ CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
+ )";
+
+ // Check
+ ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
+
+// CTTZ_ZERO_UNDEF widening.
+TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ_ZERO_UNDEF) {
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(
+ A, { getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({s16}); });
+ // Build
+ // Trunc it to s8.
+ LLT s8{LLT::scalar(8)};
+ LLT s16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+ auto MIBCTTZ_ZERO_UNDEF =
+ B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, s8, MIBTrunc);
+ AInfo Info(MF->getSubtarget());
+ LegalizerHelper Helper(*MF, Info);
+ ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 0, s16) ==
+ LegalizerHelper::LegalizeResult::Legalized);
+
+ auto CheckStr = R"(
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+ CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+ CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
+ )";
+
+ // Check
+ ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
+
+// CTTZ widening.
+TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ) {
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(A,
+ { getActionDefinitionsBuilder(G_CTTZ).legalFor({s16}); });
+ // Build
+ // Trunc it to s8.
+ LLT s8{LLT::scalar(8)};
+ LLT s16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+ auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, s8, MIBTrunc);
+ AInfo Info(MF->getSubtarget());
+ LegalizerHelper Helper(*MF, Info);
+ ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ, 0, s16) ==
+ LegalizerHelper::LegalizeResult::Legalized);
+
+ auto CheckStr = R"(
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+ CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+ CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
+ CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
+ CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
+ CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
+ )";
+
+ // Check
+ ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
} // namespace
More information about the llvm-commits
mailing list