diff options
| author | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2016-04-13 15:07:45 +0000 |
|---|---|---|
| committer | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2016-04-13 15:07:45 +0000 |
| commit | 3751d4114c8b5c8a0e78fb3d746123afc3758030 (patch) | |
| tree | fbd8393d21507e4b29ea6faced020546a0f9317b /llvm/lib/Target | |
| parent | e1680617b05785314f05e1bad08cc7c2084e40e9 (diff) | |
| download | bcm5719-llvm-3751d4114c8b5c8a0e78fb3d746123afc3758030.tar.gz bcm5719-llvm-3751d4114c8b5c8a0e78fb3d746123afc3758030.zip | |
[mips] Sign-extend i32 values truncated from previously zero-extended i32 values.
Summary:
This is a special case for MIPS64 because the architecture requires
properly 32-bit sign-extended values in the register containers.
Additionaly, we merge consecutive trunc + AssertZExt nodes in order
to avoid unnecessary sign-extensions when the extension comes from a
type smaller than i32.
Reviewers: dsanders
Subscribers: dsanders, sdardis, llvm-commits
Differential Revision: http://reviews.llvm.org/D18893
llvm-svn: 266203
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/Mips/Mips64InstrInfo.td | 16 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 34 |
2 files changed, 49 insertions, 1 deletions
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index 12ff9f32892..93a10c6cd54 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -63,6 +63,10 @@ def PowerOf2HI : PatLeaf<(imm), [{ return false; }]>; +def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ + return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32); +}]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -511,7 +515,17 @@ defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>; // truncate def : MipsPat<(trunc (assertsext GPR64:$src)), (EXTRACT_SUBREG GPR64:$src, sub_32)>; -def : MipsPat<(trunc (assertzext GPR64:$src)), +// The forward compatibility strategy employed by MIPS requires us to treat +// values as being sign extended to an infinite number of bits. This allows +// existing software to run without modification on any future MIPS +// implementation (e.g. 128-bit, or 1024-bit). Being compatible with this +// strategy requires that truncation acts as a sign-extension for values being +// fed into instructions operating on 32-bit values. Such instructions have +// undefined results if this is not true. +// For our case, this means that we can't issue an extract_subreg for nodes +// such as (trunc:i32 (assertzext:i64 X, i32)), because the sign-bit of the +// lower subreg would not be replicated into the upper half. +def : MipsPat<(trunc (assertzext_lt_i32 GPR64:$src)), (EXTRACT_SUBREG GPR64:$src, sub_32)>; def : MipsPat<(i32 (trunc GPR64:$src)), (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index be5f63f449d..37bb429f5f5 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -428,6 +428,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::AND); setTargetDAGCombine(ISD::OR); setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::AssertZext); setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2); @@ -807,6 +808,37 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo); } +static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + SDValue N0 = N->getOperand(0); + EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT(); + + if (N0.getOpcode() != ISD::TRUNCATE) + return SDValue(); + + if (N0.getOperand(0).getOpcode() != ISD::AssertZext) + return SDValue(); + + // fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x)) + // if the type of the extension of the innermost AssertZext node is + // smaller from that of the outermost node, eg: + // (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8) + // -> (trunc:i32 (AssertZext X, i8)) + SDValue WiderAssertZext = N0.getOperand(0); + EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT(); + + if (NarrowerVT.bitsLT(WiderVT)) { + SDValue NewAssertZext = DAG.getNode( + ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(), + WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT)); + return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0), + NewAssertZext); + } + + return SDValue(); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -828,6 +860,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performORCombine(N, DAG, DCI, Subtarget); case ISD::ADD: return performADDCombine(N, DAG, DCI, Subtarget); + case ISD::AssertZext: + return performAssertZextCombine(N, DAG, DCI, Subtarget); } return SDValue(); |

