[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