summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 25e80b9c736..e4a796e5478 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -1629,6 +1629,39 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
return;
}
+ bool hasOVF =
+ TLI.isOperationLegalOrCustom(N->getOpcode() == ISD::ADD ?
+ ISD::UADDO : ISD::USUBO,
+ TLI.getTypeToExpandTo(*DAG.getContext(), NVT));
+ if (hasOVF) {
+ SDVTList VTList = DAG.getVTList(NVT, NVT);
+ TargetLoweringBase::BooleanContent BoolType = TLI.getBooleanContents(NVT);
+ int RevOpc;
+ if (N->getOpcode() == ISD::ADD) {
+ RevOpc = ISD::SUB;
+ Lo = DAG.getNode(ISD::UADDO, dl, VTList, LoOps);
+ Hi = DAG.getNode(ISD::ADD, dl, NVT, makeArrayRef(HiOps, 2));
+ } else {
+ RevOpc = ISD::ADD;
+ Lo = DAG.getNode(ISD::USUBO, dl, VTList, LoOps);
+ Hi = DAG.getNode(ISD::SUB, dl, NVT, makeArrayRef(HiOps, 2));
+ }
+ SDValue OVF = Lo.getValue(1);
+
+ switch (BoolType) {
+ default:
+ case TargetLoweringBase::UndefinedBooleanContent:
+ OVF = DAG.getNode(ISD::AND, dl, NVT, DAG.getConstant(1, NVT), OVF);
+ // Fallthrough
+ case TargetLoweringBase::ZeroOrOneBooleanContent:
+ Hi = DAG.getNode(N->getOpcode(), dl, NVT, Hi, OVF);
+ break;
+ case TargetLoweringBase::ZeroOrNegativeOneBooleanContent:
+ Hi = DAG.getNode(RevOpc, dl, NVT, Hi, OVF);
+ }
+ return;
+ }
+
if (N->getOpcode() == ISD::ADD) {
Lo = DAG.getNode(ISD::ADD, dl, NVT, LoOps);
Hi = DAG.getNode(ISD::ADD, dl, NVT, makeArrayRef(HiOps, 2));
OpenPOWER on IntegriCloud