diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 0904a7ecce76..6634a197df69 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2475,10 +2475,10 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { // FIXME: Redundant check, but even less readable when factored out. if (isFP) { - if (Ty != s32 && Ty != s64 && Ty != s128) { + if (Ty != s16 && Ty != s32 && Ty != s64 && Ty != s128) { LLVM_DEBUG(dbgs() << "Unable to materialize FP " << Ty - << " constant, expected: " << s32 << " or " << s64 - << " or " << s128 << '\n'); + << " constant, expected: " << s16 << " or " << s32 + << " or " << s64 << " or " << s128 << '\n'); return false; } @@ -2512,23 +2512,20 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } } - // We allow G_CONSTANT of types < 32b. - const unsigned MovOpc = - DefSize == 64 ? AArch64::MOVi64imm : AArch64::MOVi32imm; - if (isFP) { - // Either emit a FMOV, or emit a copy to emit a normal mov. - const TargetRegisterClass &GPRRC = - DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass; - const TargetRegisterClass &FPRRC = - DefSize == 32 ? AArch64::FPR32RegClass - : (DefSize == 64 ? AArch64::FPR64RegClass - : AArch64::FPR128RegClass); - - // For 64b values, emit a constant pool load instead. - // For s32, use a cp load if we have optsize/minsize. - if (DefSize == 64 || DefSize == 128 || - (DefSize == 32 && shouldOptForSize(&MF))) { + const TargetRegisterClass &FPRRC = *getMinClassForRegBank(RB, DefSize); + // For 16, 64, and 128b values, emit a constant pool load. + switch (DefSize) { + default: + llvm_unreachable("Unexpected destination size for G_FCONSTANT?"); + case 32: + // For s32, use a cp load if we have optsize/minsize. + if (!shouldOptForSize(&MF)) + break; + LLVM_FALLTHROUGH; + case 16: + case 64: + case 128: { auto *FPImm = I.getOperand(1).getFPImm(); auto *LoadMI = emitLoadFromConstantPool(FPImm, MIB); if (!LoadMI) { @@ -2539,9 +2536,13 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { I.eraseFromParent(); return RBI.constrainGenericRegister(DefReg, FPRRC, MRI); } + } - // Nope. Emit a copy and use a normal mov instead. - const Register DefGPRReg = MRI.createVirtualRegister(&GPRRC); + // Either emit a FMOV, or emit a copy to emit a normal mov. + assert(DefSize == 32 && + "Expected constant pool loads for all sizes other than 32!"); + const Register DefGPRReg = + MRI.createVirtualRegister(&AArch64::GPR32RegClass); MachineOperand &RegOp = I.getOperand(0); RegOp.setReg(DefGPRReg); MIB.setInsertPt(MIB.getMBB(), std::next(I.getIterator())); @@ -2564,6 +2565,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { I.getOperand(1).ChangeToImmediate(Val); } + const unsigned MovOpc = + DefSize == 64 ? AArch64::MOVi64imm : AArch64::MOVi32imm; I.setDesc(TII.get(MovOpc)); constrainSelectedInstRegOperands(I, TII, TRI, RBI); return true; @@ -4236,6 +4239,13 @@ MachineInstr *AArch64InstructionSelector::emitLoadFromConstantPool( .addConstantPoolIndex(CPIdx, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC); break; + case 2: + LoadMI = + &*MIRBuilder + .buildInstr(AArch64::LDRHui, {&AArch64::FPR16RegClass}, {Adrp}) + .addConstantPoolIndex(CPIdx, 0, + AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + break; default: LLVM_DEBUG(dbgs() << "Could not load from constant pool of type " << *CPVal->getType()); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir index f7ad8fa0121e..18f907813de5 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir @@ -30,3 +30,19 @@ body: | %0:fpr(s16) = G_FCONSTANT half 1.0 $h0 = COPY %0(s16) RET_ReallyLR implicit $h0 +... +--- +name: constant_pool_load +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: constant_pool_load + ; CHECK: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) %const.0 + ; CHECK: [[LDRHui:%[0-9]+]]:fpr16 = LDRHui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) %const.0 :: (load (s16) from constant-pool) + ; CHECK: $h0 = COPY [[LDRHui]] + ; CHECK: RET_ReallyLR implicit $h0 + %0:fpr(s16) = G_FCONSTANT half 0xH000B + $h0 = COPY %0(s16) + RET_ReallyLR implicit $h0