From: Richard Sandiford Date: Wed, 11 Dec 2013 11:45:08 +0000 (+0000) Subject: [SystemZ] Optimize fcmp X, 0 in cases where X is also negated X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e54c1060a6a3f2a30b26c3289c08ae1bc8a845b9;p=oota-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197032 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index b0a8fca7de7..84b5009fd79 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1252,6 +1252,34 @@ static bool shouldSwapCmpOperands(SDValue Op0, SDValue Op1, 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(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 SystemZTargetMachine &TM, SelectionDAG &DAG, 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)); diff --git a/test/CodeGen/SystemZ/fp-cmp-04.ll b/test/CodeGen/SystemZ/fp-cmp-04.ll index 705a276563c..94f4b7cb370 100644 --- a/test/CodeGen/SystemZ/fp-cmp-04.ll +++ b/test/CodeGen/SystemZ/fp-cmp-04.ll @@ -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 +}