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 @@ -1128,6 +1128,14 @@ case TargetOpcode::G_LSHR: case TargetOpcode::G_ASHR: return narrowScalarShift(MI, TypeIdx, NarrowTy); + case TargetOpcode::G_FSHR: + case TargetOpcode::G_FSHL: + if (TypeIdx != 1) + return UnableToLegalize; + Observer.changingInstr(MI); + narrowScalarSrc(MI, NarrowTy, 3); + Observer.changedInstr(MI); + return Legalized; case TargetOpcode::G_CTLZ: case TargetOpcode::G_CTLZ_ZERO_UNDEF: case TargetOpcode::G_CTTZ: diff --git a/llvm/lib/Target/X86/X86InstrGISel.td b/llvm/lib/Target/X86/X86InstrGISel.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrGISel.td @@ -0,0 +1,35 @@ +//=----- X86InstrGISel.td - X86 GISel target pseudos -*- tablegen -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// X86 GlobalISel target pseudo instruction definitions. This is kept +// separately from the other tablegen files for organizational purposes, but +// share the same infrastructure. +// +//===----------------------------------------------------------------------===// + + +class X86GenericInstruction : GenericInstruction { + let Namespace = "X86"; +} + +// A pseudo to represent 16 bit funnel left shift modulo 32 +def G_FSHL16 : X86GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); + let hasSideEffects = false; +} + +// A pseudo to represent 16 bit funnel right shift modulo 32 +def G_FSHR16 : X86GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); + let hasSideEffects = false; +} + +def : GINodeEquiv; +def : GINodeEquiv; diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -1467,3 +1467,5 @@ // Assembler mnemonic/instruction aliases include "X86InstrAsmAlias.td" +// GISel target pseudos +include "X86InstrGISel.td" diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -350,7 +350,7 @@ MachineRegisterInfo &MRI = MF.getRegInfo(); unsigned Opcode = I.getOpcode(); - if (!isPreISelGenericOpcode(Opcode)) { + if (!isPreISelGenericOpcode(Opcode) && !I.isPreISelOpcode()) { // Certain non-generic instructions also need some special handling. if (Opcode == TargetOpcode::LOAD_STACK_GUARD) diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.h b/llvm/lib/Target/X86/X86LegalizerInfo.h --- a/llvm/lib/Target/X86/X86LegalizerInfo.h +++ b/llvm/lib/Target/X86/X86LegalizerInfo.h @@ -14,7 +14,10 @@ #ifndef LLVM_LIB_TARGET_X86_X86MACHINELEGALIZER_H #define LLVM_LIB_TARGET_X86_X86MACHINELEGALIZER_H +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" namespace llvm { @@ -31,8 +34,15 @@ public: X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM); + bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI) const override; + bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override; + +private: + bool legalizeFunnelShift(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder, + GISelChangeObserver &Observer) const; }; } // namespace llvm #endif 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 @@ -14,6 +14,7 @@ #include "X86Subtarget.h" #include "X86TargetMachine.h" #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DerivedTypes.h" @@ -153,6 +154,16 @@ .clampScalar(0, s8, sMaxScalar) .scalarize(0); + getActionDefinitionsBuilder({G_FSHL, G_FSHR}) + .legalIf([=](const LegalityQuery &Query) -> bool { + if (typeInSet(0, {s32})(Query) || (Is64Bit && typeInSet(0, {s64})(Query))) + return typeInSet(1, {s8})(Query); + return false; + }) + .clampScalar(1, s8, s8) + .customFor({s16}) + .lowerFor({s8}); + getActionDefinitionsBuilder({G_UADDE, G_UADDO, G_USUBE, G_USUBO}) .legalIf([=](const LegalityQuery &Query) -> bool { return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) || @@ -543,6 +554,41 @@ verify(*STI.getInstrInfo()); } +bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, + MachineInstr &MI) const { + MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; + MachineRegisterInfo &MRI = *MIRBuilder.getMRI(); + GISelChangeObserver &Observer = Helper.Observer; + switch (MI.getOpcode()) { + default: + return false; + case TargetOpcode::G_FSHL: + case TargetOpcode::G_FSHR: + return legalizeFunnelShift(MI, MRI, MIRBuilder, Observer); + } +} + +bool X86LegalizerInfo::legalizeFunnelShift(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder, + GISelChangeObserver &Observer) const { + const TargetInstrInfo &TII = MIRBuilder.getTII(); + auto Masked = MIRBuilder.buildAnd(LLT::scalar(8), MI.getOperand(3), MIRBuilder.buildConstant(LLT::scalar(8), 15)); + unsigned Opc = 0; + if (MI.getOpcode() == TargetOpcode::G_FSHL) + Opc = X86::G_FSHL16; + else if (MI.getOpcode() == TargetOpcode::G_FSHR) + Opc = X86::G_FSHR16; + else + return false; + + Observer.changingInstr(MI); + MI.setDesc(TII.get(Opc)); + MI.getOperand(3).setReg(Masked.getReg(0)); + Observer.changedInstr(MI); + return true; +} + bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const { return true;