From 7582d8d76f225ecbe879d6346741e925b06d1d4d Mon Sep 17 00:00:00 2001 From: Kevin Qin Date: Mon, 20 Jan 2014 02:14:05 +0000 Subject: [PATCH] [AArch64 NEON] Accept both #0.0 and #0 for comparing with floating point zero in asm parser. For FCMEQ, FCMGE, FCMGT, FCMLE and FCMLT, floating point zero will be printed as #0.0 instead of #0. To support the history codes using #0, we consider to let asm parser accept both #0.0 and #0. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199621 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64InstrNEON.td | 40 ++++++++++------ .../AArch64/AsmParser/AArch64AsmParser.cpp | 48 +++++++++++++++++++ test/MC/AArch64/neon-compare-instructions.s | 30 ++++++++++++ test/MC/AArch64/neon-diagnostics.s | 24 +++++----- test/MC/AArch64/neon-scalar-fp-compare.s | 20 ++++++++ 5 files changed, 136 insertions(+), 26 deletions(-) diff --git a/lib/Target/AArch64/AArch64InstrNEON.td b/lib/Target/AArch64/AArch64InstrNEON.td index 41c6c86f36b..3f9743989b5 100644 --- a/lib/Target/AArch64/AArch64InstrNEON.td +++ b/lib/Target/AArch64/AArch64InstrNEON.td @@ -813,29 +813,41 @@ def FCMLTvvv_2S : NeonI_compare_aliases<"fcmlt", ".2s", FCMGTvvv_2S, VPR64>; def FCMLTvvv_4S : NeonI_compare_aliases<"fcmlt", ".4s", FCMGTvvv_4S, VPR128>; def FCMLTvvv_2D : NeonI_compare_aliases<"fcmlt", ".2d", FCMGTvvv_2D, VPR128>; +def fpzero_izero_asmoperand : AsmOperandClass { + let Name = "FPZeroIZero"; + let ParserMethod = "ParseFPImm0AndImm0Operand"; + let DiagnosticType = "FPZero"; +} + +def fpzz32 : Operand, + ComplexPattern { + let ParserMatchClass = fpzero_izero_asmoperand; + let PrintMethod = "printFPZeroOperand"; + let DecoderMethod = "DecodeFPZeroOperand"; +} multiclass NeonI_fpcmpz_sizes opcode, string asmop, CondCode CC> { def _2S : NeonI_2VMisc<0b0, u, {size, 0b0}, opcode, - (outs VPR64:$Rd), (ins VPR64:$Rn, fpz32:$FPImm), + (outs VPR64:$Rd), (ins VPR64:$Rn, fpzz32:$FPImm), asmop # "\t$Rd.2s, $Rn.2s, $FPImm", [(set (v2i32 VPR64:$Rd), - (v2i32 (Neon_cmpz (v2f32 VPR64:$Rn), (f32 fpz32:$FPImm), CC)))], + (v2i32 (Neon_cmpz (v2f32 VPR64:$Rn), (f32 fpzz32:$FPImm), CC)))], NoItinerary>; def _4S : NeonI_2VMisc<0b1, u, {size, 0b0}, opcode, - (outs VPR128:$Rd), (ins VPR128:$Rn, fpz32:$FPImm), + (outs VPR128:$Rd), (ins VPR128:$Rn, fpzz32:$FPImm), asmop # "\t$Rd.4s, $Rn.4s, $FPImm", [(set (v4i32 VPR128:$Rd), - (v4i32 (Neon_cmpz (v4f32 VPR128:$Rn), (f32 fpz32:$FPImm), CC)))], + (v4i32 (Neon_cmpz (v4f32 VPR128:$Rn), (f32 fpzz32:$FPImm), CC)))], NoItinerary>; def _2D : NeonI_2VMisc<0b1, u, {size, 0b1}, opcode, - (outs VPR128:$Rd), (ins VPR128:$Rn, fpz32:$FPImm), + (outs VPR128:$Rd), (ins VPR128:$Rn, fpzz32:$FPImm), asmop # "\t$Rd.2d, $Rn.2d, $FPImm", [(set (v2i64 VPR128:$Rd), - (v2i64 (Neon_cmpz (v2f64 VPR128:$Rn), (f32 fpz32:$FPImm), CC)))], + (v2i64 (Neon_cmpz (v2f64 VPR128:$Rn), (f32 fpzz32:$FPImm), CC)))], NoItinerary>; } @@ -4512,12 +4524,12 @@ class NeonI_Scalar2SameMisc_cmpz_D_size opcode, string asmop> multiclass NeonI_Scalar2SameMisc_cmpz_SD_size opcode, string asmop> { def ssi : NeonI_Scalar2SameMisc; def ddi : NeonI_Scalar2SameMisc; @@ -4539,12 +4551,12 @@ multiclass Neon_Scalar2SameMisc_cmpz_SD_size_patterns { - def : Pat<(v1i32 (opnode (f32 FPR32:$Rn), (f32 fpz32:$FPImm))), - (INSTS FPR32:$Rn, fpz32:$FPImm)>; - def : Pat<(v1i64 (opnode (f64 FPR64:$Rn), (f32 fpz32:$FPImm))), - (INSTD FPR64:$Rn, fpz32:$FPImm)>; - def : Pat<(v1i64 (Neon_cmpz (v1f64 FPR64:$Rn), (f32 fpz32:$FPImm), CC)), - (INSTD FPR64:$Rn, fpz32:$FPImm)>; + def : Pat<(v1i32 (opnode (f32 FPR32:$Rn), (f32 fpzz32:$FPImm))), + (INSTS FPR32:$Rn, fpzz32:$FPImm)>; + def : Pat<(v1i64 (opnode (f64 FPR64:$Rn), (f32 fpzz32:$FPImm))), + (INSTD FPR64:$Rn, fpzz32:$FPImm)>; + def : Pat<(v1i64 (Neon_cmpz (v1f64 FPR64:$Rn), (f32 fpzz32:$FPImm), CC)), + (INSTD FPR64:$Rn, fpzz32:$FPImm)>; } multiclass Neon_Scalar2SameMisc_D_size_patterns &Operands); + OperandMatchResultTy + ParseFPImm0AndImm0Operand( SmallVectorImpl &Operands); + template OperandMatchResultTy ParseNamedImmOperand(SmallVectorImpl &Operands) { return ParseNamedImmOperand(SomeNamedImmMapper(), Operands); @@ -826,6 +829,10 @@ public: return CE->getValue() == N; } + bool isFPZeroIZero() const { + return isFPZero(); + } + static AArch64Operand *CreateImmWithLSL(const MCExpr *Val, unsigned ShiftAmount, bool ImplicitAmount, @@ -965,6 +972,10 @@ public: Inst.addOperand(MCOperand::CreateImm(0)); } + void addFPZeroIZeroOperands(MCInst &Inst, unsigned N) const { + addFPZeroOperands(Inst, N); + } + void addInvCondCodeOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); unsigned Encoded = A64InvertCondCode(getCondCode()); @@ -1605,6 +1616,43 @@ AArch64AsmParser::ParseFPImmOperand( return MatchOperand_Success; } +AArch64AsmParser::OperandMatchResultTy +AArch64AsmParser::ParseFPImm0AndImm0Operand( + SmallVectorImpl &Operands) { + // FIXME?: I want to live in a world where immediates must start with + // #. Please don't dash my hopes (well, do if you have a good reason). + + //This function is only used in floating compare with zero instructions to get + //those instructions accept both #0.0 and #0. + if (Parser.getTok().isNot(AsmToken::Hash)) return MatchOperand_NoMatch; + + SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat '#' + + APFloat RealVal(0.0); + if (Parser.getTok().is(AsmToken::Real)) { + if(Parser.getTok().getString() != "0.0") { + Error(S, "only #0.0 is acceptable as immediate"); + return MatchOperand_ParseFail; + } + } + else if (Parser.getTok().is(AsmToken::Integer)) { + if(Parser.getTok().getIntVal() != 0) { + Error(S, "only #0.0 is acceptable as immediate"); + return MatchOperand_ParseFail; + } + } + else { + Error(S, "only #0.0 is acceptable as immediate"); + return MatchOperand_ParseFail; + } + + Parser.Lex(); // Eat real number + SMLoc E = Parser.getTok().getLoc(); + + Operands.push_back(AArch64Operand::CreateFPImm(0.0, S, E)); + return MatchOperand_Success; +} // Automatically generated static unsigned MatchRegisterName(StringRef Name); diff --git a/test/MC/AArch64/neon-compare-instructions.s b/test/MC/AArch64/neon-compare-instructions.s index e4bc2025835..d4e3ef5f19d 100644 --- a/test/MC/AArch64/neon-compare-instructions.s +++ b/test/MC/AArch64/neon-compare-instructions.s @@ -346,10 +346,16 @@ fcmeq v0.2s, v31.2s, #0.0 fcmeq v4.4s, v7.4s, #0.0 fcmeq v29.2d, v2.2d, #0.0 + fcmeq v0.2s, v31.2s, #0 + fcmeq v4.4s, v7.4s, #0 + fcmeq v29.2d, v2.2d, #0 // CHECK: fcmeq v0.2s, v31.2s, #0.0 // encoding: [0xe0,0xdb,0xa0,0x0e] // CHECK: fcmeq v4.4s, v7.4s, #0.0 // encoding: [0xe4,0xd8,0xa0,0x4e] // CHECK: fcmeq v29.2d, v2.2d, #0.0 // encoding: [0x5d,0xd8,0xe0,0x4e] +// CHECK: fcmeq v0.2s, v31.2s, #0.0 // encoding: [0xe0,0xdb,0xa0,0x0e] +// CHECK: fcmeq v4.4s, v7.4s, #0.0 // encoding: [0xe4,0xd8,0xa0,0x4e] +// CHECK: fcmeq v29.2d, v2.2d, #0.0 // encoding: [0x5d,0xd8,0xe0,0x4e] //---------------------------------------------------------------------- // Vector Compare Mask Greater Than or Equal to Zero (Floating Point) @@ -357,10 +363,16 @@ fcmge v31.4s, v29.4s, #0.0 fcmge v3.2s, v8.2s, #0.0 fcmge v17.2d, v15.2d, #0.0 + fcmge v31.4s, v29.4s, #0 + fcmge v3.2s, v8.2s, #0 + fcmge v17.2d, v15.2d, #0 // CHECK: fcmge v31.4s, v29.4s, #0.0 // encoding: [0xbf,0xcb,0xa0,0x6e] // CHECK: fcmge v3.2s, v8.2s, #0.0 // encoding: [0x03,0xc9,0xa0,0x2e] // CHECK: fcmge v17.2d, v15.2d, #0.0 // encoding: [0xf1,0xc9,0xe0,0x6e] +// CHECK: fcmge v31.4s, v29.4s, #0.0 // encoding: [0xbf,0xcb,0xa0,0x6e] +// CHECK: fcmge v3.2s, v8.2s, #0.0 // encoding: [0x03,0xc9,0xa0,0x2e] +// CHECK: fcmge v17.2d, v15.2d, #0.0 // encoding: [0xf1,0xc9,0xe0,0x6e] //---------------------------------------------------------------------- // Vector Compare Mask Greater Than Zero (Floating Point) @@ -368,10 +380,16 @@ fcmgt v0.2s, v31.2s, #0.0 fcmgt v4.4s, v7.4s, #0.0 fcmgt v29.2d, v2.2d, #0.0 + fcmgt v0.2s, v31.2s, #0 + fcmgt v4.4s, v7.4s, #0 + fcmgt v29.2d, v2.2d, #0 // CHECK: fcmgt v0.2s, v31.2s, #0.0 // encoding: [0xe0,0xcb,0xa0,0x0e] // CHECK: fcmgt v4.4s, v7.4s, #0.0 // encoding: [0xe4,0xc8,0xa0,0x4e] // CHECK: fcmgt v29.2d, v2.2d, #0.0 // encoding: [0x5d,0xc8,0xe0,0x4e] +// CHECK: fcmgt v0.2s, v31.2s, #0.0 // encoding: [0xe0,0xcb,0xa0,0x0e] +// CHECK: fcmgt v4.4s, v7.4s, #0.0 // encoding: [0xe4,0xc8,0xa0,0x4e] +// CHECK: fcmgt v29.2d, v2.2d, #0.0 // encoding: [0x5d,0xc8,0xe0,0x4e] //---------------------------------------------------------------------- // Vector Compare Mask Less Than or Equal To Zero (Floating Point) @@ -379,10 +397,16 @@ fcmle v1.4s, v8.4s, #0.0 fcmle v3.2s, v20.2s, #0.0 fcmle v7.2d, v13.2d, #0.0 + fcmle v1.4s, v8.4s, #0 + fcmle v3.2s, v20.2s, #0 + fcmle v7.2d, v13.2d, #0 // CHECK: fcmle v1.4s, v8.4s, #0.0 // encoding: [0x01,0xd9,0xa0,0x6e] // CHECK: fcmle v3.2s, v20.2s, #0.0 // encoding: [0x83,0xda,0xa0,0x2e] // CHECK: fcmle v7.2d, v13.2d, #0.0 // encoding: [0xa7,0xd9,0xe0,0x6e] +// CHECK: fcmle v1.4s, v8.4s, #0.0 // encoding: [0x01,0xd9,0xa0,0x6e] +// CHECK: fcmle v3.2s, v20.2s, #0.0 // encoding: [0x83,0xda,0xa0,0x2e] +// CHECK: fcmle v7.2d, v13.2d, #0.0 // encoding: [0xa7,0xd9,0xe0,0x6e] //---------------------------------------------------------------------- // Vector Compare Mask Less Than Zero (Floating Point) @@ -390,10 +414,16 @@ fcmlt v16.2s, v2.2s, #0.0 fcmlt v15.4s, v4.4s, #0.0 fcmlt v5.2d, v29.2d, #0.0 + fcmlt v16.2s, v2.2s, #0 + fcmlt v15.4s, v4.4s, #0 + fcmlt v5.2d, v29.2d, #0 // CHECK: fcmlt v16.2s, v2.2s, #0.0 // encoding: [0x50,0xe8,0xa0,0x0e] // CHECK: fcmlt v15.4s, v4.4s, #0.0 // encoding: [0x8f,0xe8,0xa0,0x4e] // CHECK: fcmlt v5.2d, v29.2d, #0.0 // encoding: [0xa5,0xeb,0xe0,0x4e] +// CHECK: fcmlt v16.2s, v2.2s, #0.0 // encoding: [0x50,0xe8,0xa0,0x0e] +// CHECK: fcmlt v15.4s, v4.4s, #0.0 // encoding: [0x8f,0xe8,0xa0,0x4e] +// CHECK: fcmlt v5.2d, v29.2d, #0.0 // encoding: [0xa5,0xeb,0xe0,0x4e] diff --git a/test/MC/AArch64/neon-diagnostics.s b/test/MC/AArch64/neon-diagnostics.s index be6c163741f..aa0885708a3 100644 --- a/test/MC/AArch64/neon-diagnostics.s +++ b/test/MC/AArch64/neon-diagnostics.s @@ -680,10 +680,10 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmeq v0.16b, v1.16b, #0.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: invalid operand for instruction +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmeq v0.8b, v1.4h, #1.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: Expected floating-point immediate +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmeq v0.8b, v1.4h, #1 // CHECK-ERROR: ^ //---------------------------------------------------------------------- @@ -694,7 +694,7 @@ fcmge v31.4s, v29.2s, #0.0 fcmge v3.8b, v8.2s, #0.0 fcmle v17.8h, v15.2d, #-1.0 - fcmle v17.8h, v15.2d, #0 + fcmle v17.8h, v15.2d, #2 // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmge v31.4s, v29.2s, #0.0 @@ -702,11 +702,11 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmge v3.8b, v8.2s, #0.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: invalid operand for instruction +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmle v17.8h, v15.2d, #-1.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: Expected floating-point immediate -// CHECK-ERROR: fcmle v17.8h, v15.2d, #0 +// CHECK-ERROR: error: only #0.0 is acceptable as immediate +// CHECK-ERROR: fcmle v17.8h, v15.2d, #2 // CHECK-ERROR: ^ //---------------------------------------------------------------------- // Vector Compare Mask Greater Than Zero (Floating Point) @@ -723,10 +723,10 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmgt v4.4s, v7.4h, #0.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: expected floating-point constant #0.0 or invalid register type +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmlt v29.2d, v5.2d, #255.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: Expected floating-point immediate +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmlt v29.2d, v5.2d, #255 // CHECK-ERROR: ^ @@ -745,10 +745,10 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmge v3.8b, v8.2s, #0.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: expected floating-point constant #0.0 or invalid register type +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmle v17.2d, v15.2d, #15.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: Expected floating-point immediate +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmle v17.2d, v15.2d, #15 // CHECK-ERROR: ^ @@ -767,10 +767,10 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: fcmgt v4.4s, v7.4h, #0.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: expected floating-point constant #0.0 or invalid register type +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmlt v29.2d, v5.2d, #16.0 // CHECK-ERROR: ^ -// CHECK-ERROR: error: Expected floating-point immediate +// CHECK-ERROR: error: only #0.0 is acceptable as immediate // CHECK-ERROR: fcmlt v29.2d, v5.2d, #2 // CHECK-ERROR: ^ diff --git a/test/MC/AArch64/neon-scalar-fp-compare.s b/test/MC/AArch64/neon-scalar-fp-compare.s index a59ec0d1d6e..b798b341067 100644 --- a/test/MC/AArch64/neon-scalar-fp-compare.s +++ b/test/MC/AArch64/neon-scalar-fp-compare.s @@ -18,9 +18,13 @@ fcmeq s10, s11, #0.0 fcmeq d20, d21, #0.0 + fcmeq s10, s11, #0 + fcmeq d20, d21, #0x0 // CHECK: fcmeq s10, s11, #0.0 // encoding: [0x6a,0xd9,0xa0,0x5e] // CHECK: fcmeq d20, d21, #0.0 // encoding: [0xb4,0xda,0xe0,0x5e] +// CHECK: fcmeq s10, s11, #0.0 // encoding: [0x6a,0xd9,0xa0,0x5e] +// CHECK: fcmeq d20, d21, #0.0 // encoding: [0xb4,0xda,0xe0,0x5e] //---------------------------------------------------------------------- // Scalar Floating-point Compare Mask Greater Than Or Equal @@ -38,9 +42,13 @@ fcmge s10, s11, #0.0 fcmge d20, d21, #0.0 + fcmge s10, s11, #0 + fcmge d20, d21, #0x0 // CHECK: fcmge s10, s11, #0.0 // encoding: [0x6a,0xc9,0xa0,0x7e] // CHECK: fcmge d20, d21, #0.0 // encoding: [0xb4,0xca,0xe0,0x7e] +// CHECK: fcmge s10, s11, #0.0 // encoding: [0x6a,0xc9,0xa0,0x7e] +// CHECK: fcmge d20, d21, #0.0 // encoding: [0xb4,0xca,0xe0,0x7e] //---------------------------------------------------------------------- // Scalar Floating-point Compare Mask Greather Than @@ -58,9 +66,13 @@ fcmgt s10, s11, #0.0 fcmgt d20, d21, #0.0 + fcmgt s10, s11, #0 + fcmgt d20, d21, #0x0 // CHECK: fcmgt s10, s11, #0.0 // encoding: [0x6a,0xc9,0xa0,0x5e] // CHECK: fcmgt d20, d21, #0.0 // encoding: [0xb4,0xca,0xe0,0x5e] +// CHECK: fcmgt s10, s11, #0.0 // encoding: [0x6a,0xc9,0xa0,0x5e] +// CHECK: fcmgt d20, d21, #0.0 // encoding: [0xb4,0xca,0xe0,0x5e] //---------------------------------------------------------------------- // Scalar Floating-point Compare Mask Less Than Or Equal To Zero @@ -68,9 +80,13 @@ fcmle s10, s11, #0.0 fcmle d20, d21, #0.0 + fcmle s10, s11, #0 + fcmle d20, d21, #0x0 // CHECK: fcmle s10, s11, #0.0 // encoding: [0x6a,0xd9,0xa0,0x7e] // CHECK: fcmle d20, d21, #0.0 // encoding: [0xb4,0xda,0xe0,0x7e] +// CHECK: fcmle s10, s11, #0.0 // encoding: [0x6a,0xd9,0xa0,0x7e] +// CHECK: fcmle d20, d21, #0.0 // encoding: [0xb4,0xda,0xe0,0x7e] //---------------------------------------------------------------------- // Scalar Floating-point Compare Mask Less Than @@ -78,9 +94,13 @@ fcmlt s10, s11, #0.0 fcmlt d20, d21, #0.0 + fcmlt s10, s11, #0 + fcmlt d20, d21, #0x0 // CHECK: fcmlt s10, s11, #0.0 // encoding: [0x6a,0xe9,0xa0,0x5e] // CHECK: fcmlt d20, d21, #0.0 // encoding: [0xb4,0xea,0xe0,0x5e] +// CHECK: fcmlt s10, s11, #0.0 // encoding: [0x6a,0xe9,0xa0,0x5e] +// CHECK: fcmlt d20, d21, #0.0 // encoding: [0xb4,0xea,0xe0,0x5e] //---------------------------------------------------------------------- // Scalar Floating-point Absolute Compare Mask Greater Than Or Equal