diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.h b/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.h --- a/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.h +++ b/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.h @@ -51,6 +51,8 @@ raw_ostream &OS); void printCCOperand(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, raw_ostream &OS); + void printRDOperand(const MCInst *MI, int OpNum, const MCSubtargetInfo &STI, + raw_ostream &OS); }; } // namespace llvm diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEInstPrinter.cpp @@ -182,3 +182,9 @@ int CC = (int)MI->getOperand(OpNum).getImm(); O << VECondCodeToString((VECC::CondCode)CC); } + +void VEInstPrinter::printRDOperand(const MCInst *MI, int OpNum, + const MCSubtargetInfo &STI, raw_ostream &O) { + int RD = (int)MI->getOperand(OpNum).getImm(); + O << VERDToString((VERD::RoundingMode)RD); +} diff --git a/llvm/lib/Target/VE/VE.h b/llvm/lib/Target/VE/VE.h --- a/llvm/lib/Target/VE/VE.h +++ b/llvm/lib/Target/VE/VE.h @@ -65,6 +65,19 @@ CC_AT = 15 + 6, // Always }; } +// Enums corresponding to VE Rounding Mode. These values must be kept in +// sync with the ones in the .td file. +namespace VERD { +enum RoundingMode { + RD_NONE = 0, // According to PSW + RD_RZ = 8, // Round toward Zero + RD_RP = 9, // Round toward Plus infinity + RD_RM = 10, // Round toward Minus infinity + RD_RN = 11, // Round to Nearest (ties to Even) + RD_RA = 12, // Round to Nearest (ties to Away) + UNKNOWN +}; +} inline static const char *VECondCodeToString(VECC::CondCode CC) { switch (CC) { @@ -94,6 +107,25 @@ llvm_unreachable("Invalid cond code"); } +inline static const char *VERDToString(VERD::RoundingMode R) { + switch (R) { + case VERD::RD_NONE: + return ""; + case VERD::RD_RZ: + return ".rz"; + case VERD::RD_RP: + return ".rp"; + case VERD::RD_RM: + return ".rm"; + case VERD::RD_RN: + return ".rn"; + case VERD::RD_RA: + return ".ra"; + default: + llvm_unreachable("Invalid branch predicate"); + } +} + inline unsigned M0(unsigned Val) { return Val + 64; } inline unsigned M1(unsigned Val) { return Val; } diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -270,6 +270,11 @@ let PrintMethod = "printCCOperand" in def CCOp : Operand; +// Operand for printing out a rounding mode code. +def RDOp : Operand { + let PrintMethod = "printRDOperand"; +} + def VEhi : SDNode<"VEISD::Hi", SDTIntUnaryOp>; def VElo : SDNode<"VEISD::Lo", SDTIntUnaryOp>; @@ -335,6 +340,20 @@ def CC_AT : CC_VAL<21>; // Always true //===----------------------------------------------------------------------===// +// VE Rounding Mode +//===----------------------------------------------------------------------===// + +// Note that these values must be kept in sync with the VERD::RoundingMode enum +// values. +class RD_VAL : PatLeaf<(i32 N)>; +def RD_NONE : RD_VAL< 0>; // According to PSW +def RD_RZ : RD_VAL< 8>; // Round toward Zero +def RD_RP : RD_VAL< 9>; // Round toward Plus infinity +def RD_RM : RD_VAL<10>; // Round toward Minus infinity +def RD_RN : RD_VAL<11>; // Round to Nearest (ties to Even) +def RD_RA : RD_VAL<12>; // Round to Nearest (ties to Away) + +//===----------------------------------------------------------------------===// // VE Multiclasses for common instruction formats //===----------------------------------------------------------------------===// @@ -500,6 +519,41 @@ !strconcat(opcStr, " $sx, $sz, $sy")>; } +// Multiclass for floating point conversion instructions. +// e.g. CVTWDSX, CVTWDZX, CVTWSSX, and etc. +// sz{3-0} = rounding mode +let cz = 0, hasSideEffects = 0 in +multiclass CVTRDm opc, RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi> { + def r : RR { + bits<4> rd; + let sz{5-4} = 0; + let sz{3-0} = rd; + } + let cy = 0 in + def i : RR { + bits<4> rd; + let sz{5-4} = 0; + let sz{3-0} = rd; + } +} + +// Multiclass for floating point conversion instructions. +// e.g. CVTDW, CVTSW, CVTDL, and etc. +let cz = 0, sz = 0, hasSideEffects = 0 in +multiclass CVTm opc, RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, + SDPatternOperator OpNode = null_frag> { + def r : RR; + let cy = 0 in + def i : RR; +} + // Branch multiclass let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in multiclass BCRm opc, @@ -563,27 +617,6 @@ } } -// Multiclass for floating point conversion instructions. -// Used by CVS/CVD/FLT and others -multiclass CVTm opc, - RegisterClass RCo, ValueType Tyo, - RegisterClass RCi, ValueType Tyi, Operand immOp, - SDPatternOperator OpNode=null_frag> { - def r : RR { - let cy = 1; - let hasSideEffects = 0; - } - def i : RR { - let cy = 0; - let hasSideEffects = 0; - } -} - - //===----------------------------------------------------------------------===// // Instructions // @@ -894,65 +927,71 @@ (EXTRACT_SUBREG (SRLrr (ANDrm (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $src, sub_i32), !add(32, 64)), $val), sub_i32)>; -// 5.3.2.5. Floating-point Arithmetic Operation Instructions -let cx = 0 in -defm FAD : RRFm<"fadd.d", 0x4C, I64, f64, fadd>; -let cx = 1 in -defm FADS : RRFm<"fadd.s", 0x4C, F32, f32, fadd>; +//----------------------------------------------------------------------------- +// Section 8.7 - Floating-point Arithmetic Instructions +//----------------------------------------------------------------------------- -let cx = 0 in -defm FSB : RRFm<"fsub.d", 0x5C, I64, f64, fsub>; +// Section 8.7.1 - FAD (Floating Add) +defm FADDD : RRFm<"fadd.d", 0x4C, I64, f64, fadd>; +let cx = 1 in defm FADDS : RRFm<"fadd.s", 0x4C, F32, f32, fadd>; + +// Section 8.7.2 - FSB (Floating Subtract) +defm FSUBD : RRFm<"fsub.d", 0x5C, I64, f64, fsub>; +let cx = 1 in defm FSUBS : RRFm<"fsub.s", 0x5C, F32, f32, fsub>; + +// Section 8.7.3 - FMP (Floating Multiply) +defm FMULD : RRFm<"fmul.d", 0x4D, I64, f64, fmul>; +let cx = 1 in defm FMULS : RRFm<"fmul.s", 0x4D, F32, f32, fmul>; + +// Section 8.7.4 - FDV (Floating Divide) +defm FDIVD : RRFm<"fdiv.d", 0x5D, I64, f64, fdiv>; +let cx = 1 in defm FDIVS : RRFm<"fdiv.s", 0x5D, F32, f32, fdiv>; + +// Section 8.7.5 - FCP (Floating Compare) +defm FCMPD : RRFm<"fcmp.d", 0x7E, I64, f64>; +let cx = 1 in defm FCMPS : RRFm<"fcmp.s", 0x7E, F32, f32>; + +// Section 8.7.6 - CMS (Compare and Select Maximum/Minimum Single) +// cx: double/float, cw: max/min +defm FMAXD : RRFm<"fmax.d", 0x3E, I64, f64>; +let cx = 1 in defm FMAXS : RRFm<"fmax.s", 0x3E, F32, f32>; +let cw = 1 in defm FMIND : RRFm<"fmin.d", 0x3E, I64, f64>; +let cw = 1, cx = 1 in defm FMINS : RRFm<"fmin.s", 0x3E, F32, f32>; + +// Section 8.7.7 - FAQ (Floating Add Quadruple) +// Section 8.7.8 - FSQ (Floating Subtract Quadruple) +// Section 8.7.9 - FMQ (Floating Subtract Quadruple) +// Section 8.7.10 - FCQ (Floating Compare Quadruple) + +// Section 8.7.11 - FIX (Convert to Fixed Point) +// cx: double/float, cw: sx/zx, sz{0-3} = round +let cx = 0, cw = 0 /* sign extend */ in +defm CVTWDSX : CVTRDm<"cvt.w.d.sx", 0x4E, I32, i32, I64, f64>; +let cx = 0, cw = 1 /* zero extend */ in +defm CVTWDZX : CVTRDm<"cvt.w.d.zx", 0x4E, I32, i32, I64, f64>; +let cx = 1, cw = 0 /* sign extend */ in +defm CVTWSSX : CVTRDm<"cvt.w.s.sx", 0x4E, I32, i32, F32, f32>; +let cx = 1, cw = 1 /* zero extend */ in +defm CVTWSZX : CVTRDm<"cvt.w.s.zx", 0x4E, I32, i32, F32, f32>; + +// Section 8.7.12 - FIXX (Convert to Fixed Point) +defm CVTLD : CVTRDm<"cvt.l.d", 0x4F, I64, i64, I64, f64>; + +// Section 8.7.13 - FLT (Convert to Floating Point) +defm CVTDW : CVTm<"cvt.d.w", 0x5E, I64, f64, I32, i32, sint_to_fp>; let cx = 1 in -defm FSBS : RRFm<"fsub.s", 0x5C, F32, f32, fsub>; +defm CVTSW : CVTm<"cvt.s.w", 0x5E, F32, f32, I32, i32, sint_to_fp>; -let cx = 0 in -defm FMP : RRFm<"fmul.d", 0x4D, I64, f64, fmul>; -let cx = 1 in -defm FMPS : RRFm<"fmul.s", 0x4D, F32, f32, fmul>; +// Section 8.7.14 - FLTX (Convert to Floating Point) +defm CVTDL : CVTm<"cvt.d.l", 0x5F, I64, f64, I64, i64, sint_to_fp>; -let cx = 0 in -defm FDV : RRFm<"fdiv.d", 0x5D, I64, f64, fdiv>; -let cx = 1 in -defm FDVS : RRFm<"fdiv.s", 0x5D, F32, f32, fdiv>; +// Section 8.7.15 - CVS (Convert to Single-format) +defm CVTSD : CVTm<"cvt.s.d", 0x1F, F32, f32, I64, f64, fpround>; -// FCP instruction -let cx = 0 in -defm FCP : RRm<"fcmp.d", 0x7E, I64, f64>; -let cx = 1 in -defm FCPS : RRm<"fcmp.s", 0x7E, F32, f32>; - -// FCM -let cw = 0 in { - let cx = 0 in - defm FCMA : RRm<"fmax.d", 0x3E, I64, f64>; - let cx = 1 in - defm FCMAS : RRm<"fmax.s", 0x3E, F32, f32>; -} -let cw = 1 in { - let cx = 0 in - defm FCMI : RRm<"fmin.d", 0x3E, I64, f64>; - let cx = 1 in - defm FCMIS : RRm<"fmin.s", 0x3E, F32, f32>; -} +// Section 8.7.16 - CVD (Convert to Double-format) +defm CVTDS : CVTm<"cvt.d.s", 0x0F, I64, f64, F32, f32, fpextend>; -let cx = 0, cw = 0 /* sign extend */, cz = 1, sz = 0 /* round toward zero */ in -defm FIX : CVTm<"cvt.w.d.sx.rz", 0x4E, I32, i32, I64, f64, simm7, fp_to_sint>; -let cx = 1, cw = 0 /* sign extend */, cz = 1, sz = 0 /* round toward zero */ in -defm FIXS : CVTm<"cvt.w.s.sx.rz", 0x4E, I32, i32, F32, f32, simm7, fp_to_sint>; -let cx = 0, cz = 1, sz = 0 /* round toward zero */ in -defm FIXX : CVTm<"cvt.l.d.rz", 0x4F, I64, i64, I64, f64, simm7, fp_to_sint>; -let cz = 0, sz = 0 in { - let cx = 0 in - defm FLT : CVTm<"cvt.d.w", 0x5E, I64, f64, I32, i32, simm7, sint_to_fp>; - let cx = 1 in - defm FLTS : CVTm<"cvt.s.w", 0x5E, F32, f32, I32, i32, simm7, sint_to_fp>; - let cx = 0 in - defm FLTX : CVTm<"cvt.d.l", 0x5F, I64, f64, I64, i64, simm7, sint_to_fp>; - let cx = 0 in - defm CVS : CVTm<"cvt.s.d", 0x1F, F32, f32, I64, f64, simm7, fpround>; - let cx = 0 in - defm CVD : CVTm<"cvt.d.s", 0x0F, I64, f64, F32, f32, simm7, fpextend>; -} +// Section 8.7.17 - CVQ (Convert to Single-format) // Control-flow @@ -1111,6 +1150,8 @@ // Cast to i32 def : Pat<(i32 (trunc i64:$src)), (ADDSWSXrm (EXTRACT_SUBREG $src, sub_i32), 0)>; +def : Pat<(i32 (fp_to_sint I64:$reg)), (CVTWDSXr RD_RZ, $reg)>; +def : Pat<(i32 (fp_to_sint F32:$reg)), (CVTWSSXr RD_RZ, $reg)>; // Cast to i64 def : Pat<(sext_inreg I64:$src, i32), @@ -1120,10 +1161,11 @@ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (ADDSWSXrm $sy, 0), sub_i32)>; def : Pat<(i64 (zext i32:$sy)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (ADDSWZXrm $sy, 0), sub_i32)>; -def : Pat<(i64 (fp_to_sint f32:$sy)), (FIXXr (CVDr $sy))>; +def : Pat<(i64 (fp_to_sint f32:$sy)), (CVTLDr RD_RZ, (CVTDSr $sy))>; +def : Pat<(i64 (fp_to_sint I64:$reg)), (CVTLDr RD_RZ, $reg)>; // Cast to f32 -def : Pat<(f32 (sint_to_fp i64:$sy)), (CVSr (FLTXr i64:$sy))>; +def : Pat<(f32 (sint_to_fp i64:$sy)), (CVTSDr (CVTDLr i64:$sy))>; def : Pat<(i64 (anyext i32:$sy)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $sy, sub_i32)>; @@ -1322,14 +1364,14 @@ def : Pat<(i32 (setcc f64:$LHS, f64:$RHS, cond:$cond)), (EXTRACT_SUBREG (CMOVDrm (fcond2cc $cond), - (FCPrr f64:$LHS, f64:$RHS), + (FCMPDrr f64:$LHS, f64:$RHS), !add(63, 64), (ORim 0, 0)), sub_i32)>; def : Pat<(i32 (setcc f32:$LHS, f32:$RHS, cond:$cond)), (EXTRACT_SUBREG (CMOVSrm (fcond2cc $cond), - (FCPSrr f32:$LHS, f32:$RHS), + (FCMPSrr f32:$LHS, f32:$RHS), !add(63, 64), (ORim 0, 0)), sub_i32)>; @@ -1339,34 +1381,34 @@ // MAX/MIN %res, %lhs, %rhs def : Pat<(f64 (selectcc f64:$LHS, f64:$RHS, f64:$LHS, f64:$RHS, SETOGT)), - (FCMArr $LHS, $RHS)>; + (FMAXDrr $LHS, $RHS)>; def : Pat<(f32 (selectcc f32:$LHS, f32:$RHS, f32:$LHS, f32:$RHS, SETOGT)), - (FCMASrr $LHS, $RHS)>; + (FMAXSrr $LHS, $RHS)>; def : Pat<(i64 (selectcc i64:$LHS, i64:$RHS, i64:$LHS, i64:$RHS, SETGT)), (MAXSLrr $LHS, $RHS)>; def : Pat<(i32 (selectcc i32:$LHS, i32:$RHS, i32:$LHS, i32:$RHS, SETGT)), (MAXSWSXrr $LHS, $RHS)>; def : Pat<(f64 (selectcc f64:$LHS, f64:$RHS, f64:$LHS, f64:$RHS, SETOGE)), - (FCMArr $LHS, $RHS)>; + (FMAXDrr $LHS, $RHS)>; def : Pat<(f32 (selectcc f32:$LHS, f32:$RHS, f32:$LHS, f32:$RHS, SETOGE)), - (FCMASrr $LHS, $RHS)>; + (FMAXSrr $LHS, $RHS)>; def : Pat<(i64 (selectcc i64:$LHS, i64:$RHS, i64:$LHS, i64:$RHS, SETGE)), (MAXSLrr $LHS, $RHS)>; def : Pat<(i32 (selectcc i32:$LHS, i32:$RHS, i32:$LHS, i32:$RHS, SETGE)), (MAXSWSXrr $LHS, $RHS)>; def : Pat<(f64 (selectcc f64:$LHS, f64:$RHS, f64:$LHS, f64:$RHS, SETOLT)), - (FCMIrr $LHS, $RHS)>; + (FMINDrr $LHS, $RHS)>; def : Pat<(f32 (selectcc f32:$LHS, f32:$RHS, f32:$LHS, f32:$RHS, SETOLT)), - (FCMISrr $LHS, $RHS)>; + (FMINSrr $LHS, $RHS)>; def : Pat<(i64 (selectcc i64:$LHS, i64:$RHS, i64:$LHS, i64:$RHS, SETLT)), (MINSLrr $LHS, $RHS)>; def : Pat<(i32 (selectcc i32:$LHS, i32:$RHS, i32:$LHS, i32:$RHS, SETLT)), (MINSWSXrr $LHS, $RHS)>; def : Pat<(f64 (selectcc f64:$LHS, f64:$RHS, f64:$LHS, f64:$RHS, SETOLE)), - (FCMIrr $LHS, $RHS)>; + (FMINDrr $LHS, $RHS)>; def : Pat<(f32 (selectcc f32:$LHS, f32:$RHS, f32:$LHS, f32:$RHS, SETOLE)), - (FCMISrr $LHS, $RHS)>; + (FMINSrr $LHS, $RHS)>; def : Pat<(i64 (selectcc i64:$LHS, i64:$RHS, i64:$LHS, i64:$RHS, SETLE)), (MINSLrr $LHS, $RHS)>; def : Pat<(i32 (selectcc i32:$LHS, i32:$RHS, i32:$LHS, i32:$RHS, SETLE)), @@ -1388,9 +1430,9 @@ def : Pat<(i64 (selectcc i64:$l, i64:$r, i64:$t, i64:$f, CCUIOp:$cond)), (CMOVLrr (icond2cc $cond), (CMPULrr $l, $r), $t, $f)>; def : Pat<(i64 (selectcc f32:$l, f32:$r, i64:$t, i64:$f, cond:$cond)), - (CMOVSrr (fcond2cc $cond), (FCPSrr $l, $r), $t, $f)>; + (CMOVSrr (fcond2cc $cond), (FCMPSrr $l, $r), $t, $f)>; def : Pat<(i64 (selectcc f64:$l, f64:$r, i64:$t, i64:$f, cond:$cond)), - (CMOVDrr (fcond2cc $cond), (FCPrr $l, $r), $t, $f)>; + (CMOVDrr (fcond2cc $cond), (FCMPDrr $l, $r), $t, $f)>; // selectcc for i32 result def : Pat<(i32 (selectcc i32:$l, i32:$r, i32:$t, i32:$f, CCSIOp:$cond)), @@ -1424,14 +1466,14 @@ def : Pat<(i32 (selectcc f32:$l, f32:$r, i32:$t, i32:$f, cond:$cond)), (EXTRACT_SUBREG (CMOVSrr (fcond2cc $cond), - (FCPSrr $l, $r), + (FCMPSrr $l, $r), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $t, sub_i32), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $f, sub_i32)), sub_i32)>; def : Pat<(i32 (selectcc f64:$l, f64:$r, i32:$t, i32:$f, cond:$cond)), (EXTRACT_SUBREG (CMOVDrr (fcond2cc $cond), - (FCPrr $l, $r), + (FCMPDrr $l, $r), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $t, sub_i32), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $f, sub_i32)), sub_i32)>; @@ -1446,9 +1488,9 @@ def : Pat<(f64 (selectcc i64:$l, i64:$r, f64:$t, f64:$f, CCUIOp:$cond)), (CMOVLrr (icond2cc $cond), (CMPULrr $l, $r), $t, $f)>; def : Pat<(f64 (selectcc f32:$l, f32:$r, f64:$t, f64:$f, cond:$cond)), - (CMOVSrr (fcond2cc $cond), (FCPSrr $l, $r), $t, $f)>; + (CMOVSrr (fcond2cc $cond), (FCMPSrr $l, $r), $t, $f)>; def : Pat<(f64 (selectcc f64:$l, f64:$r, f64:$t, f64:$f, cond:$cond)), - (CMOVDrr (fcond2cc $cond), (FCPrr $l, $r), $t, $f)>; + (CMOVDrr (fcond2cc $cond), (FCMPDrr $l, $r), $t, $f)>; // selectcc for f32 result def : Pat<(f32 (selectcc i32:$l, i32:$r, f32:$t, f32:$f, CCSIOp:$cond)), @@ -1482,14 +1524,14 @@ def : Pat<(f32 (selectcc f32:$l, f32:$r, f32:$t, f32:$f, cond:$cond)), (EXTRACT_SUBREG (CMOVSrr (fcond2cc $cond), - (FCPSrr $l, $r), + (FCMPSrr $l, $r), (INSERT_SUBREG (f64 (IMPLICIT_DEF)), $t, sub_f32), (INSERT_SUBREG (f64 (IMPLICIT_DEF)), $f, sub_f32)), sub_f32)>; def : Pat<(f32 (selectcc f64:$l, f64:$r, f32:$t, f32:$f, cond:$cond)), (EXTRACT_SUBREG (CMOVDrr (fcond2cc $cond), - (FCPrr $l, $r), + (FCMPDrr $l, $r), (INSERT_SUBREG (f64 (IMPLICIT_DEF)), $t, sub_f32), (INSERT_SUBREG (f64 (IMPLICIT_DEF)), $f, sub_f32)), sub_f32)>;