[llvm] r197032 - [SystemZ] Optimize fcmp X, 0 in cases where X is also negated

Richard Sandiford rsandifo at linux.vnet.ibm.com
Wed Dec 11 03:45:08 PST 2013


Author: rsandifo
Date: Wed Dec 11 05:45:08 2013
New Revision: 197032

URL: http://llvm.org/viewvc/llvm-project?rev=197032&view=rev
Log:
[SystemZ] Optimize fcmp X, 0 in cases where X is also negated

In such cases it's often better to test the result of the negation instead,
since the negation also sets CC.

Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
    llvm/trunk/test/CodeGen/SystemZ/fp-cmp-04.ll

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=197032&r1=197031&r2=197032&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Wed Dec 11 05:45:08 2013
@@ -1252,6 +1252,34 @@ static bool shouldSwapCmpOperands(SDValu
   return false;
 }
 
+// Return a version of comparison CC mask CCMask in which the LT and GT
+// actions are swapped.
+static unsigned reverseCCMask(unsigned CCMask) {
+  return ((CCMask & SystemZ::CCMASK_CMP_EQ) |
+          (CCMask & SystemZ::CCMASK_CMP_GT ? SystemZ::CCMASK_CMP_LT : 0) |
+          (CCMask & SystemZ::CCMASK_CMP_LT ? SystemZ::CCMASK_CMP_GT : 0) |
+          (CCMask & SystemZ::CCMASK_CMP_UO));
+}
+
+// CmpOp0 and CmpOp1 are being compared using CC mask CCMask.  Check whether
+// CmpOp0 is a floating-point result that is also negated and if CmpOp1
+// is zero.  In this case we can use the negation to set CC, so avoiding
+// separate LOAD AND TEST and LOAD (NEGATIVE/COMPLEMENT) instructions.
+static void adjustForFNeg(SDValue &CmpOp0, SDValue &CmpOp1, unsigned &CCMask) {
+  ConstantFPSDNode *C1 = dyn_cast<ConstantFPSDNode>(CmpOp1);
+  if (C1 && C1->isZero()) {
+    for (SDNode::use_iterator I = CmpOp0->use_begin(), E = CmpOp0->use_end();
+         I != E; ++I) {
+      SDNode *N = *I;
+      if (N->getOpcode() == ISD::FNEG) {
+        CmpOp0 = SDValue(N, 0);
+        CCMask = reverseCCMask(CCMask);
+        return;
+      }
+    }
+  }
+}
+
 // Return true if shift operation N has an in-range constant shift value.
 // Store it in ShiftVal if so.
 static bool isSimpleShift(SDValue N, unsigned &ShiftVal) {
@@ -1463,14 +1491,12 @@ static SDValue emitCmp(const SystemZTarg
 
   if (shouldSwapCmpOperands(CmpOp0, CmpOp1, ICmpType)) {
     std::swap(CmpOp0, CmpOp1);
-    CCMask = ((CCMask & SystemZ::CCMASK_CMP_EQ) |
-              (CCMask & SystemZ::CCMASK_CMP_GT ? SystemZ::CCMASK_CMP_LT : 0) |
-              (CCMask & SystemZ::CCMASK_CMP_LT ? SystemZ::CCMASK_CMP_GT : 0) |
-              (CCMask & SystemZ::CCMASK_CMP_UO));
+    CCMask = reverseCCMask(CCMask);
   }
 
   adjustForTestUnderMask(DAG, Opcode, CmpOp0, CmpOp1, CCValid, CCMask,
                          ICmpType);
+  adjustForFNeg(CmpOp0, CmpOp1, CCMask);
   if (Opcode == SystemZISD::ICMP || Opcode == SystemZISD::TM)
     return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1,
                        DAG.getConstant(ICmpType, MVT::i32));

Modified: llvm/trunk/test/CodeGen/SystemZ/fp-cmp-04.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/fp-cmp-04.ll?rev=197032&r1=197031&r2=197032&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/fp-cmp-04.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/fp-cmp-04.ll Wed Dec 11 05:45:08 2013
@@ -365,3 +365,43 @@ store:
 exit:
   ret float %res
 }
+
+; Test another form of f7 in which the condition is based on the unnegated
+; result.  This is what InstCombine would produce.
+define float @f18(float %dummy, float %a, float *%dest) {
+; CHECK-LABEL: f18:
+; CHECK: lnebr %f0, %f2
+; CHECK-NEXT: jl .L{{.*}}
+; CHECK: br %r14
+entry:
+  %abs = call float @llvm.fabs.f32(float %a)
+  %res = fsub float -0.0, %abs
+  %cmp = fcmp ogt float %abs, 0.0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store float %res, float *%dest
+  br label %exit
+
+exit:
+  ret float %res
+}
+
+; Similarly for f8.
+define float @f19(float %dummy, float %a, float *%dest) {
+; CHECK-LABEL: f19:
+; CHECK: lcebr %f0, %f2
+; CHECK-NEXT: jle .L{{.*}}
+; CHECK: br %r14
+entry:
+  %res = fsub float -0.0, %a
+  %cmp = fcmp oge float %a, 0.0
+  br i1 %cmp, label %exit, label %store
+
+store:
+  store float %res, float *%dest
+  br label %exit
+
+exit:
+  ret float %res
+}





More information about the llvm-commits mailing list