From 5ca5daa6b936bc457b928f3f3d47c7def8b5f706 Mon Sep 17 00:00:00 2001 From: John Brawn Date: Thu, 20 Apr 2017 10:13:54 +0000 Subject: [PATCH] [AArch64] Fix handling of zero immediate in fmov instructions Currently fmov #0 with a vector destination is handle incorrectly and results in fmov #-1.9375 being emitted but should instead give an error. This is due to the way we cope with fmov #0 with a scalar destination being an alias of fmov zr, so fix this by actually doing it through an alias. Differential Revision: https://reviews.llvm.org/D31949 llvm-svn: 300830 --- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 5 ++++ .../Target/AArch64/AsmParser/AArch64AsmParser.cpp | 28 +++++++--------------- llvm/test/MC/AArch64/basic-a64-diagnostics.s | 10 ++++---- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 4449412..82e9c5a 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2586,6 +2586,11 @@ def FMOVS0 : Pseudo<(outs FPR32:$Rd), (ins), [(set f32:$Rd, (fpimm0))]>, def FMOVD0 : Pseudo<(outs FPR64:$Rd), (ins), [(set f64:$Rd, (fpimm0))]>, Sched<[WriteF]>; } +// Similarly add aliases +def : InstAlias<"fmov $Rd, #0.0", (FMOVWHr FPR16:$Rd, WZR), 0>, + Requires<[HasFullFP16]>; +def : InstAlias<"fmov $Rd, #0.0", (FMOVWSr FPR32:$Rd, WZR), 0>; +def : InstAlias<"fmov $Rd, #0.0", (FMOVXDr FPR64:$Rd, XZR), 0>; //===----------------------------------------------------------------------===// // Floating point conversion instruction. diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 347cffe..d7bbc2b 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -2116,10 +2116,15 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) { uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); Val = AArch64_AM::getFP64Imm(APInt(64, IntVal)); - // Check for out of range values. As an exception, we let Zero through, - // as we handle that special case in post-processing before matching in - // order to use the zero register for it. - if (Val == -1 && !RealVal.isPosZero()) { + // Check for out of range values. As an exception we let Zero through, + // but as tokens instead of an FPImm so that it can be matched by the + // appropriate alias if one exists. + if (RealVal.isPosZero()) { + Parser.Lex(); // Eat the token. + Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext())); + Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext())); + return MatchOperand_Success; + } else if (Val == -1) { TokError("expected compatible register or floating-point constant"); return MatchOperand_ParseFail; } @@ -3646,21 +3651,6 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } } - // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR. - if (NumOperands == 3 && Tok == "fmov") { - AArch64Operand &RegOp = static_cast(*Operands[1]); - AArch64Operand &ImmOp = static_cast(*Operands[2]); - if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) { - unsigned zreg = - !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains( - RegOp.getReg()) - ? AArch64::WZR - : AArch64::XZR; - Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(), - Op.getEndLoc(), getContext()); - } - } - MCInst Inst; // First try to match against the secondary set of tables containing the // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2"). diff --git a/llvm/test/MC/AArch64/basic-a64-diagnostics.s b/llvm/test/MC/AArch64/basic-a64-diagnostics.s index ca51332..d37c0d5 100644 --- a/llvm/test/MC/AArch64/basic-a64-diagnostics.s +++ b/llvm/test/MC/AArch64/basic-a64-diagnostics.s @@ -1812,11 +1812,11 @@ // CHECK-ERROR-NEXT: fmov s15, #0x100 // CHECK-ERROR-NEXT: ^ - ;; No particular reason, but a striking omission - fmov d0, #0.0 -// CHECK-ERROR-AARCH64: error: expected compatible register or floating-point constant -// CHECK-ERROR-AARCH64-NEXT: fmov d0, #0.0 -// CHECK-ERROR-AARCH64-NEXT: ^ + ;; Not possible to fmov ZR to a whole vector + fmov v0.4s, #0.0 +// CHECK-ERROR: error: invalid operand for instruction +// CHECK-ERROR-NEXT: fmov v0.4s, #0.0 +// CHECK-ERROR-NEXT: ^ //------------------------------------------------------------------------------ // Floating-point <-> integer conversion -- 2.7.4