mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 17:31:50 +00:00
Two things:
1. teach SimplifySetCC that '(srl (ctlz x), 5) == 0' is really x != 0. 2. Teach visitSELECT_CC to use SimplifySetCC instead of calling it and ignoring the result. This allows us to compile: bool %test(ulong %x) { %tmp = setlt ulong %x, 4294967296 ret bool %tmp } to: _test: cntlzw r2, r3 cmplwi cr0, r3, 1 srwi r2, r2, 5 li r3, 0 beq cr0, LBB1_2 ; LBB1_1: ; mr r3, r2 LBB1_2: ; blr instead of: _test: addi r2, r3, -1 cntlzw r2, r2 cntlzw r3, r3 srwi r2, r2, 5 cmplwi cr0, r2, 0 srwi r2, r3, 5 li r3, 0 bne cr0, LBB1_2 ; LBB1_1: ; mr r3, r2 LBB1_2: ; blr This isn't wonderful, but it's an improvement. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30513 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ac924c8248
commit
5f42a240ba
@ -22,7 +22,6 @@
|
||||
// FIXME: shr X, (and Y,31) -> shr X, Y (TRICKY!)
|
||||
// FIXME: mul (x, const) -> shifts + adds
|
||||
// FIXME: undef values
|
||||
// FIXME: make truncate see through SIGN_EXTEND and AND
|
||||
// FIXME: divide by zero is currently left unfolded. do we want to turn this
|
||||
// into an undef?
|
||||
// FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
|
||||
@ -1721,14 +1720,26 @@ SDOperand DAGCombiner::visitSELECT_CC(SDNode *N) {
|
||||
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
|
||||
ISD::CondCode CC = cast<CondCodeSDNode>(N4)->get();
|
||||
|
||||
// Determine if the condition we're dealing with is constant
|
||||
SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC, false);
|
||||
//ConstantSDNode *SCCC = dyn_cast_or_null<ConstantSDNode>(SCC.Val);
|
||||
|
||||
// fold select_cc lhs, rhs, x, x, cc -> x
|
||||
if (N2 == N3)
|
||||
return N2;
|
||||
|
||||
// Determine if the condition we're dealing with is constant
|
||||
SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC, false);
|
||||
|
||||
if (ConstantSDNode *SCCC = dyn_cast_or_null<ConstantSDNode>(SCC.Val)) {
|
||||
if (SCCC->getValue())
|
||||
return N2; // cond always true -> true val
|
||||
else
|
||||
return N3; // cond always false -> false val
|
||||
}
|
||||
|
||||
// Fold to a simpler select_cc
|
||||
if (SCC.Val && SCC.getOpcode() == ISD::SETCC)
|
||||
return DAG.getNode(ISD::SELECT_CC, N2.getValueType(),
|
||||
SCC.getOperand(0), SCC.getOperand(1), N2, N3,
|
||||
SCC.getOperand(2));
|
||||
|
||||
// If we can fold this based on the true/false value, do so.
|
||||
if (SimplifySelectOps(N, N2, N3))
|
||||
return SDOperand(N, 0); // Don't revisit N.
|
||||
@ -3340,6 +3351,30 @@ SDOperand DAGCombiner::SimplifySetCC(MVT::ValueType VT, SDOperand N0,
|
||||
case ISD::SETGE: return DAG.getConstant((int64_t)C0 >= (int64_t)C1, VT);
|
||||
}
|
||||
} else {
|
||||
// If the LHS is '(srl (ctlz x), 5)', the RHS is 0/1, and this is an
|
||||
// equality comparison, then we're just comparing whether X itself is
|
||||
// zero.
|
||||
if (N0.getOpcode() == ISD::SRL && (C1 == 0 || C1 == 1) &&
|
||||
N0.getOperand(0).getOpcode() == ISD::CTLZ &&
|
||||
N0.getOperand(1).getOpcode() == ISD::Constant) {
|
||||
unsigned ShAmt = cast<ConstantSDNode>(N0.getOperand(1))->getValue();
|
||||
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
||||
ShAmt == Log2_32(MVT::getSizeInBits(N0.getValueType()))) {
|
||||
if ((C1 == 0) == (Cond == ISD::SETEQ)) {
|
||||
// (srl (ctlz x), 5) == 0 -> X != 0
|
||||
// (srl (ctlz x), 5) != 1 -> X != 0
|
||||
Cond = ISD::SETNE;
|
||||
} else {
|
||||
// (srl (ctlz x), 5) != 0 -> X == 0
|
||||
// (srl (ctlz x), 5) == 1 -> X == 0
|
||||
Cond = ISD::SETEQ;
|
||||
}
|
||||
SDOperand Zero = DAG.getConstant(0, N0.getValueType());
|
||||
return DAG.getSetCC(VT, N0.getOperand(0).getOperand(0),
|
||||
Zero, Cond);
|
||||
}
|
||||
}
|
||||
|
||||
// If the LHS is a ZERO_EXTEND, perform the comparison on the input.
|
||||
if (N0.getOpcode() == ISD::ZERO_EXTEND) {
|
||||
unsigned InSize = MVT::getSizeInBits(N0.getOperand(0).getValueType());
|
||||
|
Loading…
Reference in New Issue
Block a user