From 584940e3c65aca9e8329cae7b3ffda8ea51da81d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 13 Dec 2013 15:50:30 +0000 Subject: [PATCH] [SystemZ] Optimize X [!=]= Y in cases where X - Y or Y - X is also computed In those cases it's better to compare the result of the subtraction against zero. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197239 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZISelLowering.cpp | 21 +++++++++++++++++++++ test/CodeGen/SystemZ/int-cmp-44.ll | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 6c443b59f79..baef2c1d0b3 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1271,6 +1271,26 @@ static unsigned reverseCCMask(unsigned CCMask) { (CCMask & SystemZ::CCMASK_CMP_UO)); } +// Check whether C tests for equality between X and Y and whether X - Y +// or Y - X is also computed. In that case it's better to compare the +// result of the subtraction against zero. +static void adjustForSubtraction(SelectionDAG &DAG, Comparison &C) { + if (C.CCMask == SystemZ::CCMASK_CMP_EQ || + C.CCMask == SystemZ::CCMASK_CMP_NE) { + for (SDNode::use_iterator I = C.Op0->use_begin(), E = C.Op0->use_end(); + I != E; ++I) { + SDNode *N = *I; + if (N->getOpcode() == ISD::SUB && + ((N->getOperand(0) == C.Op0 && N->getOperand(1) == C.Op1) || + (N->getOperand(0) == C.Op1 && N->getOperand(1) == C.Op0))) { + C.Op0 = SDValue(N, 0); + C.Op1 = DAG.getConstant(0, N->getValueType(0)); + return; + } + } + } +} + // Check whether C compares a floating-point value with zero and if that // floating-point value is also negated. In this case we can use the // negation to set CC, so avoiding separate LOAD AND TEST and @@ -1540,6 +1560,7 @@ static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, C.CCMask &= ~SystemZ::CCMASK_CMP_UO; adjustZeroCmp(DAG, C); adjustSubwordCmp(DAG, C); + adjustForSubtraction(DAG, C); } if (shouldSwapCmpOperands(C)) { diff --git a/test/CodeGen/SystemZ/int-cmp-44.ll b/test/CodeGen/SystemZ/int-cmp-44.ll index 7f537e9de75..8ab67f70e62 100644 --- a/test/CodeGen/SystemZ/int-cmp-44.ll +++ b/test/CodeGen/SystemZ/int-cmp-44.ll @@ -845,3 +845,23 @@ store: exit: ret i64 %ext } + +; Try a form of f7 in which the subtraction operands are compared directly. +define i32 @f41(i32 %a, i32 %b, i32 *%dest) { +; CHECK-LABEL: f41: +; CHECK: s %r2, 0(%r4) +; CHECK-NEXT: jne .L{{.*}} +; CHECK: br %r14 +entry: + %cur = load i32 *%dest + %res = sub i32 %a, %cur + %cmp = icmp ne i32 %a, %cur + br i1 %cmp, label %exit, label %store + +store: + store i32 %b, i32 *%dest + br label %exit + +exit: + ret i32 %res +} -- 2.34.1