summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorVasileios Kalintiris <Vasileios.Kalintiris@imgtec.com>2016-04-13 15:07:45 +0000
committerVasileios Kalintiris <Vasileios.Kalintiris@imgtec.com>2016-04-13 15:07:45 +0000
commit3751d4114c8b5c8a0e78fb3d746123afc3758030 (patch)
treefbd8393d21507e4b29ea6faced020546a0f9317b /llvm/lib/Target
parente1680617b05785314f05e1bad08cc7c2084e40e9 (diff)
downloadbcm5719-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.td16
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.cpp34
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();
OpenPOWER on IntegriCloud