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 @@ -72,6 +72,10 @@ setLegalizerInfoAVX512DQ(); setLegalizerInfoAVX512BW(); + const LLT s16 = LLT::scalar(16); + const LLT s32 = LLT::scalar(32); + const LLT s64 = LLT::scalar(64); + getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN) .scalarize(0) .minScalar(0, LLT::scalar(32)) @@ -93,6 +97,41 @@ getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall(); + + if (Subtarget.is64Bit()) { + if (Subtarget.hasPOPCNT()) { + // popcount + 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 + 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()); } @@ -288,22 +327,6 @@ LegacyInfo.setAction({G_MERGE_VALUES, 1, s128}, LegacyLegalizeActions::Legal); LegacyInfo.setAction({G_UNMERGE_VALUES, s128}, LegacyLegalizeActions::Legal); - if (Subtarget.hasPOPCNT()) { - // popcount - 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); - } - } void X86LegalizerInfo::setLegalizerInfoSSE1() { diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-ctpop-32.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-ctpop-32.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-ctpop-32.mir @@ -0,0 +1,70 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 +# RUN: llc -mtriple=i386-linux-gnu -mattr=+popcnt -run-pass=legalizer %s -o - | FileCheck %s + +# test popcount for s8, s16, and s32 + +--- +name: test_ctpop8 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctpop8 + ; CHECK: [[DEF:%[0-9]+]]:_(s8) = IMPLICIT_DEF + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[DEF]](s8) + ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]](s16) + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[CTPOP]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s8) = COPY [[TRUNC]](s8) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s8) + %0:_(s8) = IMPLICIT_DEF + %1:_(s8) = G_CTPOP %0 + %2:_(s8) = COPY %1(s8) + RET 0, implicit %2 + +... +--- +name: test_ctpop32 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctpop32 + ; CHECK: [[DEF:%[0-9]+]]:_(s32) = IMPLICIT_DEF + ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s32) = G_CTPOP [[DEF]](s32) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[CTPOP]](s32) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s32) + %0:_(s32) = IMPLICIT_DEF + %1:_(s32) = G_CTPOP %0 + %2:_(s32) = COPY %1(s32) + RET 0, implicit %2 + +... +--- +name: test_ctpop16 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctpop16 + ; CHECK: [[DEF:%[0-9]+]]:_(s16) = IMPLICIT_DEF + ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[DEF]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]](s16) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s16) + %0:_(s16) = IMPLICIT_DEF + %1:_(s16) = G_CTPOP %0 + %2:_(s16) = COPY %1(s16) + RET 0, implicit %2 + +... diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros-32.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros-32.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros-32.mir @@ -0,0 +1,72 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 +# RUN: llc -mtriple=i386-linux-gnu -mattr=+lzcnt -run-pass=legalizer %s -o - | FileCheck %s + +# test count leading zeros for s8, s16, and s32 + +--- +name: test_ctlz8 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctlz8 + ; CHECK: [[DEF:%[0-9]+]]:_(s8) = IMPLICIT_DEF + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[DEF]](s8) + ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s16) = G_CTLZ [[ZEXT]](s16) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[CTLZ]], [[C]] + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s8) = COPY [[TRUNC]](s8) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s8) + %0:_(s8) = IMPLICIT_DEF + %1:_(s8) = G_CTLZ %0 + %2:_(s8) = COPY %1(s8) + RET 0, implicit %2 + +... +--- +name: test_ctlz32 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctlz32 + ; CHECK: [[DEF:%[0-9]+]]:_(s32) = IMPLICIT_DEF + ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[DEF]](s32) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[CTLZ]](s32) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s32) + %0:_(s32) = IMPLICIT_DEF + %1:_(s32) = G_CTLZ %0 + %2:_(s32) = COPY %1(s32) + RET 0, implicit %2 + +... +--- +name: test_ctlz16 +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1: + ; CHECK-LABEL: name: test_ctlz16 + ; CHECK: [[DEF:%[0-9]+]]:_(s16) = IMPLICIT_DEF + ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s16) = G_CTLZ [[DEF]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTLZ]](s16) + ; CHECK-NEXT: RET 0, implicit [[COPY]](s16) + %0:_(s16) = IMPLICIT_DEF + %1:_(s16) = G_CTLZ %0 + %2:_(s16) = COPY %1(s16) + RET 0, implicit %2 + +...