diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -98,6 +98,53 @@ getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall(); + if (Subtarget.is64Bit()) { + getActionDefinitionsBuilder(G_BSWAP) + .legalFor({s32, s64}) + .widenScalarToNextPow2(0, /*Min=*/32) + .clampScalar(0, s32, s64); + + if (Subtarget.hasPOPCNT()) { + // popcount (POPCNT) + getActionDefinitionsBuilder(G_CTPOP) + .legalFor({{s16, s16}, {s32, s32}, {s64, s64}}) + .widenScalarToNextPow2(1, /*Min=*/16) + .clampScalar(1, s16, s64); + } + + if (Subtarget.hasLZCNT()) { + // count leading zeros (LZCNT) + getActionDefinitionsBuilder(G_CTLZ) + .legalFor({{s16, s16}, {s32, s32}, {s64, s64}}) + .widenScalarToNextPow2(1, /*Min=*/16) + .clampScalar(1, s16, s64); + } + } else { // 32-bit + getActionDefinitionsBuilder(G_BSWAP) + .legalIf([=](const LegalityQuery &Query) { + // workaround for legalFor + return Query.Types[0] == s32; + }) + .widenScalarToNextPow2(0, /*Min=*/32) + .clampScalar(0, s32, s32); + + if (Subtarget.hasPOPCNT()) { + // popcount + getActionDefinitionsBuilder(G_CTPOP) + .legalFor({{s16, s16}, {s32, s32}}) + .widenScalarToNextPow2(1, /*Min=*/16) + .clampScalar(1, s16, s32); + } + + if (Subtarget.hasLZCNT()) { + // count leading zeros (LZCNT) + getActionDefinitionsBuilder(G_CTLZ) + .legalFor({{s16, s16}, {s32, s32}}) + .widenScalarToNextPow2(1, /*Min=*/16) + .clampScalar(1, s16, s32); + } + } + LegacyInfo.computeTables(); verify(*STI.getInstrInfo()); }