summaryrefslogtreecommitdiff
path: root/lib/Target/SystemZ
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-12-11 11:45:08 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-12-11 11:45:08 +0000
commite54c1060a6a3f2a30b26c3289c08ae1bc8a845b9 (patch)
tree9cdb87baabfdf2ab0619894ffef44de7212952dd /lib/Target/SystemZ
parent3c14ba596248d64cc3f464e244d23abf934cde3e (diff)
downloadllvm-e54c1060a6a3f2a30b26c3289c08ae1bc8a845b9.tar.gz
llvm-e54c1060a6a3f2a30b26c3289c08ae1bc8a845b9.tar.bz2
llvm-e54c1060a6a3f2a30b26c3289c08ae1bc8a845b9.tar.xz
[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
Diffstat (limited to 'lib/Target/SystemZ')
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp34
1 files changed, 30 insertions, 4 deletions
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp
index b0a8fca7de..84b5009fd7 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<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 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));