Index: llvm/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1155,36 +1155,44 @@ GIComplexPatternEquiv; // Floating-point immediate. -def fpimm16 : Operand, - FPImmLeafgetValueAPF(); uint32_t enc = AArch64_AM::getFP16Imm(InVal); return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); - }]>> { + }]>; + +def fpimm32XForm : SDNodeXFormgetValueAPF(); + uint32_t enc = AArch64_AM::getFP32Imm(InVal); + return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); + }]>; + +def fpimm64XForm : SDNodeXFormgetValueAPF(); + uint32_t enc = AArch64_AM::getFP64Imm(InVal); + return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); + }]>; + +def fpimm16 : Operand, + FPImmLeaf { let ParserMatchClass = FPImmOperand; let PrintMethod = "printFPImmOperand"; } + def fpimm32 : Operand, FPImmLeafgetValueAPF(); - uint32_t enc = AArch64_AM::getFP32Imm(InVal); - return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); - }]>> { + }], fpimm32XForm> { let ParserMatchClass = FPImmOperand; let PrintMethod = "printFPImmOperand"; } def fpimm64 : Operand, FPImmLeafgetValueAPF(); - uint32_t enc = AArch64_AM::getFP64Imm(InVal); - return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); - }]>> { + }], fpimm64XForm> { let ParserMatchClass = FPImmOperand; let PrintMethod = "printFPImmOperand"; } @@ -1198,6 +1206,13 @@ return Imm.isExactlyValue(+0.0); }]>; +def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">, + GISDNodeXFormEquiv; +def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">, + GISDNodeXFormEquiv; +def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">, + GISDNodeXFormEquiv; + // Vector lane operands class AsmVectorIndex : AsmOperandClass { let Name = NamePrefix # "IndexRange" # Min # "_" # Max; Index: llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -244,12 +244,6 @@ Register VecReg, unsigned LaneIdx, MachineIRBuilder &MIRBuilder) const; - /// Helper function for selecting G_FCONSTANT. If the G_FCONSTANT can be - /// materialized using a FMOV instruction, then update MI and return it. - /// Otherwise, do nothing and return a nullptr. - MachineInstr *emitFMovForFConstant(MachineInstr &MI, - MachineRegisterInfo &MRI) const; - /// Emit a CSet for an integer compare. /// /// \p DefReg and \p SrcReg are expected to be 32-bit scalar registers. @@ -393,6 +387,12 @@ int OpIdx = -1) const; void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx = -1) const; + void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI, + int OpIdx = -1) const; + void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI, + int OpIdx = -1) const; + void renderFPImm64(MachineInstrBuilder &MIB, const MachineInstr &MI, + int OpIdx = -1) const; // Materialize a GlobalValue or BlockAddress using a movz+movk sequence. void materializeLargeCMVal(MachineInstr &I, const Value *V, @@ -2425,10 +2425,6 @@ : (DefSize == 64 ? AArch64::FPR64RegClass : AArch64::FPR128RegClass); - // Can we use a FMOV instruction to represent the immediate? - if (emitFMovForFConstant(I, MRI)) - return true; - // For 64b values, emit a constant pool load instead. if (DefSize == 64 || DefSize == 128) { auto *FPImm = I.getOperand(1).getFPImm(); @@ -4387,39 +4383,6 @@ return &*InsElt; } -MachineInstr *AArch64InstructionSelector::emitFMovForFConstant( - MachineInstr &I, MachineRegisterInfo &MRI) const { - assert(I.getOpcode() == TargetOpcode::G_FCONSTANT && - "Expected a G_FCONSTANT!"); - MachineOperand &ImmOp = I.getOperand(1); - unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); - - // Only handle 32 and 64 bit defs for now. - if (DefSize != 32 && DefSize != 64) - return nullptr; - - // Don't handle null values using FMOV. - if (ImmOp.getFPImm()->isNullValue()) - return nullptr; - - // Get the immediate representation for the FMOV. - const APFloat &ImmValAPF = ImmOp.getFPImm()->getValueAPF(); - int Imm = DefSize == 32 ? AArch64_AM::getFP32Imm(ImmValAPF) - : AArch64_AM::getFP64Imm(ImmValAPF); - - // If this is -1, it means the immediate can't be represented as the requested - // floating point value. Bail. - if (Imm == -1) - return nullptr; - - // Update MI to represent the new FMOV instruction, constrain it, and return. - ImmOp.ChangeToImmediate(Imm); - unsigned MovOpc = DefSize == 32 ? AArch64::FMOVSi : AArch64::FMOVDi; - I.setDesc(TII.get(MovOpc)); - constrainSelectedInstRegOperands(I, TII, TRI, RBI); - return &I; -} - MachineInstr * AArch64InstructionSelector::emitCSetForICMP(Register DefReg, unsigned Pred, MachineIRBuilder &MIRBuilder, @@ -5965,6 +5928,33 @@ MIB.addImm(Enc); } +void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB, + const MachineInstr &MI, + int OpIdx) const { + assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 && + "Expected G_FCONSTANT"); + MIB.addImm( + AArch64_AM::getFP16Imm(MI.getOperand(1).getFPImm()->getValueAPF())); +} + +void AArch64InstructionSelector::renderFPImm32(MachineInstrBuilder &MIB, + const MachineInstr &MI, + int OpIdx) const { + assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 && + "Expected G_FCONSTANT"); + MIB.addImm( + AArch64_AM::getFP32Imm(MI.getOperand(1).getFPImm()->getValueAPF())); +} + +void AArch64InstructionSelector::renderFPImm64(MachineInstrBuilder &MIB, + const MachineInstr &MI, + int OpIdx) const { + assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 && + "Expected G_FCONSTANT"); + MIB.addImm( + AArch64_AM::getFP64Imm(MI.getOperand(1).getFPImm()->getValueAPF())); +} + bool AArch64InstructionSelector::isLoadStoreOfNumBytes( const MachineInstr &MI, unsigned NumBytes) const { if (!MI.mayLoadOrStore()) Index: llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir +++ llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir @@ -15,3 +15,18 @@ %0:fpr(s16) = G_FCONSTANT half 0.0 $h0 = COPY %0(s16) RET_ReallyLR implicit $h0 +... +--- +name: one +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: one + ; CHECK: [[FMOVHi:%[0-9]+]]:fpr16 = FMOVHi 112 + ; CHECK: $h0 = COPY [[FMOVHi]] + ; CHECK: RET_ReallyLR implicit $h0 + %0:fpr(s16) = G_FCONSTANT half 1.0 + $h0 = COPY %0(s16) + RET_ReallyLR implicit $h0