mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-16 16:16:45 +00:00
[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. llvm-svn: 197032
This commit is contained in:
parent
ffff4e9e61
commit
533c977c68
@ -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));
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user