[SystemZ] Optimize X [!=]= Y in cases where X - Y or Y - X is also computed
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Fri, 13 Dec 2013 15:50:30 +0000 (15:50 +0000)
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Fri, 13 Dec 2013 15:50:30 +0000 (15:50 +0000)
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
test/CodeGen/SystemZ/int-cmp-44.ll

index 6c443b59f7982f6c766056ab4776c0daf98f3886..baef2c1d0b3b4e58c31a8af55606a373c692b661 100644 (file)
@@ -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)) {
index 7f537e9de75fd9005258705638cbd29d8b2f4e6f..8ab67f70e6264280e40777b2c84d9e2fc9559b7d 100644 (file)
@@ -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
+}