Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5382,6 +5382,22 @@ return false; } +static int getIntImmCost(int64_t Val, unsigned RegSize) { + if (AArch64_AM::isAnyMOVWMovAlias(Val, RegSize)) + return 1; + + if (Val < 0) + Val = ~Val; + + // Calculate how many moves we will need to materialize this constant. + unsigned LZ = countLeadingZeros((uint64_t)Val); + return (RegSize - LZ + 15) / 16; +} + +// The cost is actually exactly the same for mov+fmov vs. adrp+ldr; however +// the mov+fmov sequence is always better because of the reduced cache +// pressure. The timings are still the same if you consider movw+movk+fmov +// vs. adrp+ldr (it's one instruction longer, but the movw+movk is fused). bool AArch64TargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { bool IsLegal = false; // We can materialize #0.0 as fmov $Rd, XZR for 64-bit, 32-bit cases, and @@ -5394,15 +5410,18 @@ IsLegal = AArch64_AM::getFP32Imm(ImmInt) != -1 || Imm.isPosZero(); else if (VT == MVT::f16 && Subtarget->hasFullFP16()) IsLegal = AArch64_AM::getFP16Imm(ImmInt) != -1 || Imm.isPosZero(); - // TODO: fmov h0, w0 is also legal, however on't have an isel pattern to + // TODO: fmov h0, w0 is also legal, however we don't have an isel pattern to // generate that fmov. // If we can not materialize in immediate field for fmov, check if the // value can be encoded as the immediate operand of a logical instruction. // The immediate value will be created with either MOVZ, MOVN, or ORR. + // We limit to 2 instrdduction at most. if (!IsLegal && (VT == MVT::f64 || VT == MVT::f32)) - IsLegal = AArch64_AM::isAnyMOVWMovAlias(ImmInt.getZExtValue(), - VT.getSizeInBits()); + // For f64 is not obviously worthwhile to emit up a five-instruction + // sequence vs. a two instruction constant-pool load. So we limit to + // at maximum of 2 moves to match and adrl+ldr cost. + IsLegal = getIntImmCost(ImmInt.getZExtValue(), VT.getSizeInBits()) <= 2; LLVM_DEBUG(dbgs() << (IsLegal ? "Legal " : "Illegal ") << VT.getEVTString() << " imm value: "; Imm.dump();); Index: test/CodeGen/AArch64/arm64-fp-imm.ll =================================================================== --- test/CodeGen/AArch64/arm64-fp-imm.ll +++ test/CodeGen/AArch64/arm64-fp-imm.ll @@ -10,12 +10,11 @@ ret double 0x400921FB54442D18 } -; CHECK: literal4 -; CHECK: .long 1078530011 define float @bar() { ; CHECK: _bar: -; CHECK: adrp x[[REG:[0-9]+]], lCPI1_0@PAGE -; CHECK: ldr s0, [x[[REG]], lCPI1_0@PAGEOFF] +; CHECK: mov [[REG:w[0-9]+]], #4059 +; CHECK: movk [[REG]], #16457, lsl #16 +; CHECK: fmov s0, [[REG]] ; CHECK-NEXT: ret ret float 0x400921FB60000000 } Index: test/CodeGen/AArch64/fpimm.ll =================================================================== --- test/CodeGen/AArch64/fpimm.ll +++ test/CodeGen/AArch64/fpimm.ll @@ -54,8 +54,9 @@ ; LARGE: mov [[REG:w[0-9]+]], #4059 ; LARGE-NEXT: movk [[REG]], #16457, lsl #16 ; LARGE-NEXT: fmov s0, [[REG]] -; TINY-LABEL: check_float2 -; TINY: ldr s0, .LCPI2_0 +; TINY-LABEL: check_float2 +; TINY: mov [[REG:w[0-9]+]], #4059 +; TINY-NEXT: movk [[REG]], #16457, lsl #16 define float @check_float2() { ret float 3.14159274101257324218750 } Index: test/CodeGen/AArch64/win_cst_pool.ll =================================================================== --- test/CodeGen/AArch64/win_cst_pool.ll +++ test/CodeGen/AArch64/win_cst_pool.ll @@ -2,22 +2,22 @@ ; RUN: llc < %s -mtriple=aarch64-win32-gnu | FileCheck -check-prefix=MINGW %s define double @double() { - ret double 0x0000000000800001 + ret double 0x2000000000800001 } -; CHECK: .globl __real@0000000000800001 -; CHECK-NEXT: .section .rdata,"dr",discard,__real@0000000000800001 +; CHECK: .globl __real@2000000000800001 +; CHECK-NEXT: .section .rdata,"dr",discard,__real@2000000000800001 ; CHECK-NEXT: .p2align 3 -; CHECK-NEXT: __real@0000000000800001: -; CHECK-NEXT: .xword 8388609 +; CHECK-NEXT: __real@2000000000800001: +; CHECK-NEXT: .xword 2305843009222082561 ; CHECK: double: -; CHECK: adrp x8, __real@0000000000800001 -; CHECK-NEXT: ldr d0, [x8, __real@0000000000800001] +; CHECK: adrp x8, __real@2000000000800001 +; CHECK-NEXT: ldr d0, [x8, __real@2000000000800001] ; CHECK-NEXT: ret ; MINGW: .section .rdata,"dr" ; MINGW-NEXT: .p2align 3 ; MINGW-NEXT: [[LABEL:\.LC.*]]: -; MINGW-NEXT: .xword 8388609 +; MINGW-NEXT: .xword 2305843009222082561 ; MINGW: double: ; MINGW: adrp x8, [[LABEL]] ; MINGW-NEXT: ldr d0, [x8, [[LABEL]]]