Skip to content

Commit

Permalink
Re-commit: [mips] abs.[ds], and neg.[ds] should be allowed regardless…
Browse files Browse the repository at this point in the history
… of -enable-no-nans-fp-math

Summary:
They behave in accordance with the Has2008 and ABS2008 configuration bits of the processor which are used to select between the 1985 and 2008 versions of IEEE 754. In 1985 mode, these instructions are arithmetic (i.e. they raise invalid operation exceptions when given NaN), in 2008 mode they are non-arithmetic (i.e. they are copies).

nmadd.[ds], and nmsub.[ds] are still subject to -enable-no-nans-fp-math because the ISA spec does not explicitly state that they obey Has2008 and ABS2008.

Fixed the issue with the previous version of this patch (r205628). A pre-existing 'let Predicate =' statement was removing some predicates that were necessary for FP64 to behave correctly.

Reviewers: matheusalmeida

Reviewed By: matheusalmeida

Differential Revision: http://llvm-reviews.chandlerc.com/D3274



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205844 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
dsandersllvm committed Apr 9, 2014
1 parent 7184f49 commit e777fb4
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 119 deletions.
70 changes: 0 additions & 70 deletions lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,6 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);

if (!TM.Options.NoNaNsFPMath) {
setOperationAction(ISD::FABS, MVT::f32, Custom);
setOperationAction(ISD::FABS, MVT::f64, Custom);
}

if (hasMips64()) {
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
Expand Down Expand Up @@ -334,11 +329,6 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::FREM, MVT::f32, Expand);
setOperationAction(ISD::FREM, MVT::f64, Expand);

if (!TM.Options.NoNaNsFPMath) {
setOperationAction(ISD::FNEG, MVT::f32, Expand);
setOperationAction(ISD::FNEG, MVT::f64, Expand);
}

setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);

setOperationAction(ISD::VAARG, MVT::Other, Expand);
Expand Down Expand Up @@ -779,7 +769,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::SETCC: return lowerSETCC(Op, DAG);
case ISD::VASTART: return lowerVASTART(Op, DAG);
case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG);
case ISD::FABS: return lowerFABS(Op, DAG);
case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG);
case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG);
Expand Down Expand Up @@ -1771,65 +1760,6 @@ MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
return lowerFCOPYSIGN32(Op, DAG, Subtarget->hasExtractInsert());
}

static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG,
bool HasExtractInsert) {
SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
SDLoc DL(Op);

// If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
// to i32.
SDValue X = (Op.getValueType() == MVT::f32) ?
DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) :
DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
Const1);

// Clear MSB.
if (HasExtractInsert)
Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32,
DAG.getRegister(Mips::ZERO, MVT::i32),
DAG.getConstant(31, MVT::i32), Const1, X);
else {
SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
}

if (Op.getValueType() == MVT::f32)
return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res);

SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
Op.getOperand(0), DAG.getConstant(0, MVT::i32));
return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
}

static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG,
bool HasExtractInsert) {
SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
SDLoc DL(Op);

// Bitcast to integer node.
SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0));

// Clear MSB.
if (HasExtractInsert)
Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64,
DAG.getRegister(Mips::ZERO_64, MVT::i64),
DAG.getConstant(63, MVT::i32), Const1, X);
else {
SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1);
Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1);
}

return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res);
}

SDValue
MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const {
if (Subtarget->hasMips64() && (Op.getValueType() == MVT::f64))
return lowerFABS64(Op, DAG, Subtarget->hasExtractInsert());

return lowerFABS32(Op, DAG, Subtarget->hasExtractInsert());
}

SDValue MipsTargetLowering::
lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
// check the depth
Expand Down
14 changes: 6 additions & 8 deletions lib/Target/Mips/MipsInstrFPU.td
Original file line number Diff line number Diff line change
Expand Up @@ -322,14 +322,12 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
def PseudoCVT_D64_L : ABSS_FT<"", FGR64Opnd, GPR64Opnd, II_CVT>;
}

let Predicates = [NoNaNsFPMath, HasStdEnc] in {
def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>,
ABSS_FM<0x5, 16>;
def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>,
ABSS_FM<0x7, 16>;
defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>;
defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>;
}
def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>,
ABSS_FM<0x5, 16>;
def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>,
ABSS_FM<0x7, 16>;
defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>;
defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>;

def FSQRT_S : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>,
ABSS_FM<0x4, 16>;
Expand Down
3 changes: 1 addition & 2 deletions lib/Target/Mips/MipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">,
AssemblerPredicate<"FeatureMips32">;
def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">,
AssemblerPredicate<"FeatureMips32">;
def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">,
AssemblerPredicate<"FeatureMips32">;
def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">;
def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">,
AssemblerPredicate<"!FeatureMips16">;
def NotDSP : Predicate<"!Subtarget.hasDSP()">;
Expand Down
50 changes: 18 additions & 32 deletions test/CodeGen/Mips/fabs.ll
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 | FileCheck %s -check-prefix=32
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32r2 | FileCheck %s -check-prefix=32R2
; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64 -mattr=n64 | FileCheck %s -check-prefix=64
; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64r2 -mattr=n64 | FileCheck %s -check-prefix=64R2
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 -enable-no-nans-fp-math | FileCheck %s -check-prefix=NO-NAN
; Check that abs.[ds] is selected and does not depend on -enable-no-nans-fp-math
; They obey the Has2008 and ABS2008 configuration bits which govern the
; conformance to IEEE 754 (1985) and IEEE 754 (2008). When these bits are not
; present, they confirm to 1985.
; In 1985 mode, abs.[ds] are arithmetic (i.e. they raise invalid operation
; exceptions when given NaN's). In 2008 mode, they are non-arithmetic (i.e.
; they are copies and don't raise any exceptions).

define float @foo0(float %a) nounwind readnone {
entry:
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 | FileCheck %s
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32r2 | FileCheck %s
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 -enable-no-nans-fp-math | FileCheck %s

; 32: lui $[[T0:[0-9]+]], 32767
; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
; 32: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
; 32: mtc1 $[[AND]], $f0
; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64 | FileCheck %s
; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64 -enable-no-nans-fp-math | FileCheck %s

; 32R2: ins $[[INS:[0-9]+]], $zero, 31, 1
; 32R2: mtc1 $[[INS]], $f0
define float @foo0(float %a) nounwind readnone {
entry:

; NO-NAN: abs.s
; CHECK-LABEL: foo0
; CHECK: abs.s

%call = tail call float @fabsf(float %a) nounwind readnone
ret float %call
Expand All @@ -26,24 +28,8 @@ declare float @fabsf(float) nounwind readnone
define double @foo1(double %a) nounwind readnone {
entry:

; 32: lui $[[T0:[0-9]+]], 32767
; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
; 32: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
; 32: mtc1 $[[AND]], $f1

; 32R2: ins $[[INS:[0-9]+]], $zero, 31, 1
; 32R2: mtc1 $[[INS]], $f1

; 64: daddiu $[[T0:[0-9]+]], $zero, 1
; 64: dsll $[[T1:[0-9]+]], ${{[0-9]+}}, 63
; 64: daddiu $[[MSK0:[0-9]+]], $[[T1]], -1
; 64: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
; 64: dmtc1 $[[AND]], $f0

; 64R2: dins $[[INS:[0-9]+]], $zero, 63, 1
; 64R2: dmtc1 $[[INS]], $f0

; NO-NAN: abs.d
; CHECK-LABEL: foo1:
; CHECK: abs.d

%call = tail call double @fabs(double %a) nounwind readnone
ret double %call
Expand Down
15 changes: 15 additions & 0 deletions test/CodeGen/Mips/fmadd1.ll
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
; Check that madd.[ds], msub.[ds], nmadd.[ds], and nmsub.[ds] are supported
; correctly.
; The spec for nmadd.[ds], and nmsub.[ds] does not state that they obey the
; the Has2008 and ABS2008 configuration bits which govern the conformance to
; IEEE 754 (1985) and IEEE 754 (2008). These instructions are therefore only
; available when -enable-no-nans-fp-math is given.

; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -enable-no-nans-fp-math | FileCheck %s -check-prefix=32R2 -check-prefix=CHECK
; RUN: llc < %s -march=mips64el -mcpu=mips64r2 -mattr=n64 -enable-no-nans-fp-math | FileCheck %s -check-prefix=64R2 -check-prefix=CHECK
; RUN: llc < %s -march=mipsel -mcpu=mips32r2 | FileCheck %s -check-prefix=32R2NAN -check-prefix=CHECK
; RUN: llc < %s -march=mips64el -mcpu=mips64r2 -mattr=n64 | FileCheck %s -check-prefix=64R2NAN -check-prefix=CHECK

define float @FOO0float(float %a, float %b, float %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO0float:
; CHECK: madd.s
%mul = fmul float %a, %b
%add = fadd float %mul, %c
Expand All @@ -14,6 +22,7 @@ entry:

define float @FOO1float(float %a, float %b, float %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO1float:
; CHECK: msub.s
%mul = fmul float %a, %b
%sub = fsub float %mul, %c
Expand All @@ -23,6 +32,7 @@ entry:

define float @FOO2float(float %a, float %b, float %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO2float:
; 32R2: nmadd.s
; 64R2: nmadd.s
; 32R2NAN: madd.s
Expand All @@ -35,6 +45,7 @@ entry:

define float @FOO3float(float %a, float %b, float %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO3float:
; 32R2: nmsub.s
; 64R2: nmsub.s
; 32R2NAN: msub.s
Expand All @@ -47,6 +58,7 @@ entry:

define double @FOO10double(double %a, double %b, double %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO10double:
; CHECK: madd.d
%mul = fmul double %a, %b
%add = fadd double %mul, %c
Expand All @@ -56,6 +68,7 @@ entry:

define double @FOO11double(double %a, double %b, double %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO11double:
; CHECK: msub.d
%mul = fmul double %a, %b
%sub = fsub double %mul, %c
Expand All @@ -65,6 +78,7 @@ entry:

define double @FOO12double(double %a, double %b, double %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO12double:
; 32R2: nmadd.d
; 64R2: nmadd.d
; 32R2NAN: madd.d
Expand All @@ -77,6 +91,7 @@ entry:

define double @FOO13double(double %a, double %b, double %c) nounwind readnone {
entry:
; CHECK-LABEL: FOO13double:
; 32R2: nmsub.d
; 64R2: nmsub.d
; 32R2NAN: msub.d
Expand Down
27 changes: 20 additions & 7 deletions test/CodeGen/Mips/fneg.ll
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
; RUN: llc < %s -march=mipsel -mcpu=mips32 | FileCheck %s
; Check that abs.[ds] is selected and does not depend on -enable-no-nans-fp-math
; They obey the Has2008 and ABS2008 configuration bits which govern the
; conformance to IEEE 754 (1985) and IEEE 754 (2008). When these bits are not
; present, they confirm to 1985.
; In 1985 mode, abs.[ds] are arithmetic (i.e. they raise invalid operation
; exceptions when given NaN's). In 2008 mode, they are non-arithmetic (i.e.
; they are copies and don't raise any exceptions).

define float @foo0(i32 %a, float %d) nounwind readnone {
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 | FileCheck %s
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32r2 | FileCheck %s
; RUN: llc < %s -mtriple=mipsel-linux-gnu -mcpu=mips32 -enable-no-nans-fp-math | FileCheck %s

; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64 | FileCheck %s
; RUN: llc < %s -mtriple=mips64el-linux-gnu -mcpu=mips64 -enable-no-nans-fp-math | FileCheck %s

define float @foo0(float %d) nounwind readnone {
entry:
; CHECK-NOT: neg.s
; CHECK-LABEL: foo0:
; CHECK: neg.s
%sub = fsub float -0.000000e+00, %d
ret float %sub
}

define double @foo1(i32 %a, double %d) nounwind readnone {
define double @foo1(double %d) nounwind readnone {
entry:
; CHECK: foo1
; CHECK-NOT: neg.d
; CHECK: jr
; CHECK-LABEL: foo1:
; CHECK: neg.d
%sub = fsub double -0.000000e+00, %d
ret double %sub
}

0 comments on commit e777fb4

Please sign in to comment.