diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -144,8 +144,9 @@ bool selectBrJT(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectTLSGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI) const; - unsigned emitConstantPoolEntry(Constant *CPVal, MachineFunction &MF) const; - MachineInstr *emitLoadFromConstantPool(Constant *CPVal, + unsigned emitConstantPoolEntry(const Constant *CPVal, + MachineFunction &MF) const; + MachineInstr *emitLoadFromConstantPool(const Constant *CPVal, MachineIRBuilder &MIRBuilder) const; // Emit a vector concat operation. @@ -2046,6 +2047,20 @@ if (emitFMovForFConstant(I, MRI)) return true; + // For 64b values, emit a constant pool load instead. + if (DefSize == 64) { + auto *FPImm = I.getOperand(1).getFPImm(); + MachineIRBuilder MIB(I); + auto *LoadMI = emitLoadFromConstantPool(FPImm, MIB); + if (!LoadMI) { + LLVM_DEBUG(dbgs() << "Failed to load double constant pool entry\n"); + return false; + } + MIB.buildCopy({DefReg}, {LoadMI->getOperand(0).getReg()}); + I.eraseFromParent(); + return RBI.constrainGenericRegister(DefReg, FPRRC, MRI); + } + // Nope. Emit a copy and use a normal mov instead. const Register DefGPRReg = MRI.createVirtualRegister(&GPRRC); MachineOperand &RegOp = I.getOperand(0); @@ -3572,7 +3587,7 @@ } unsigned -AArch64InstructionSelector::emitConstantPoolEntry(Constant *CPVal, +AArch64InstructionSelector::emitConstantPoolEntry(const Constant *CPVal, MachineFunction &MF) const { Type *CPTy = CPVal->getType(); Align Alignment = MF.getDataLayout().getPrefTypeAlign(CPTy); @@ -3582,7 +3597,7 @@ } MachineInstr *AArch64InstructionSelector::emitLoadFromConstantPool( - Constant *CPVal, MachineIRBuilder &MIRBuilder) const { + const Constant *CPVal, MachineIRBuilder &MIRBuilder) const { unsigned CPIdx = emitConstantPoolEntry(CPVal, MIRBuilder.getMF()); auto Adrp = diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-imm.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-imm.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-imm.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-imm.mir @@ -6,6 +6,7 @@ define void @imm_s32_gpr() { ret void } define void @imm_s64_gpr() { ret void } + define void @test_f64_cp() { ret void } ... @@ -49,3 +50,29 @@ %0(s64) = G_CONSTANT i64 1234 $x0 = COPY %0(s64) ... + +# 64b FP immediates need to be loaded. +--- +name: test_f64_cp +legalized: true +regBankSelected: true +liveins: + - { reg: '$d0' } +body: | + bb.1 (%ir-block.0): + liveins: $d0 + + ; CHECK-LABEL: name: test_f64_cp + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) %const.0 + ; CHECK: [[LDRDui:%[0-9]+]]:fpr64 = LDRDui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) %const.0 + ; CHECK: [[FADDDrr:%[0-9]+]]:fpr64 = FADDDrr [[COPY]], [[LDRDui]] + ; CHECK: $d0 = COPY [[FADDDrr]] + ; CHECK: RET_ReallyLR implicit $d0 + %0:fpr(s64) = COPY $d0 + %1:fpr(s64) = G_FCONSTANT double 0x3FEFF7CED916872B + %2:fpr(s64) = G_FADD %0, %1 + $d0 = COPY %2(s64) + RET_ReallyLR implicit $d0 + +...