1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-21 18:22:53 +01:00

[DAGCombiner] Fold SETCC(FREEZE(x),const) to FREEZE(SETCC(x,const)) if SETCC is used by BRCOND

This patch adds a peephole optimization `SETCC(FREEZE(x),const)` => `FREEZE(SETCC(x,const))`
if the SETCC is only used by BRCOND.

Combined with `BRCOND(FREEZE(X)) => BRCOND(X)`, this leads to a nice improvement in the generated assembly when x is a masked loaded value.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D105344
This commit is contained in:
Juneyoung Lee 2021-07-02 21:00:43 +09:00
parent 2e57fe1d7d
commit bab6d38daf
3 changed files with 59 additions and 6 deletions

View File

@ -1565,6 +1565,8 @@ public:
bool isOne() const { return Value->isOne(); }
bool isNullValue() const { return Value->isZero(); }
bool isAllOnesValue() const { return Value->isMinusOne(); }
bool isMaxSignedValue() const { return Value->isMaxValue(true); }
bool isMinSignedValue() const { return Value->isMinValue(true); }
bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }

View File

@ -10223,9 +10223,62 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
bool PreferSetCC =
N->hasOneUse() && N->use_begin()->getOpcode() == ISD::BRCOND;
SDValue Combined = SimplifySetCC(
N->getValueType(0), N->getOperand(0), N->getOperand(1),
cast<CondCodeSDNode>(N->getOperand(2))->get(), SDLoc(N), !PreferSetCC);
ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
EVT VT = N->getValueType(0);
// SETCC(FREEZE(X), CONST, Cond)
// =>
// FREEZE(SETCC(X, CONST, Cond))
// This is correct if FREEZE(X) has one use and SETCC(FREEZE(X), CONST, Cond)
// isn't equivalent to true or false.
// For example, SETCC(FREEZE(X), -128, SETULT) cannot be folded to
// FREEZE(SETCC(X, -128, SETULT)) because X can be poison.
//
// This transformation is beneficial because visitBRCOND can fold
// BRCOND(FREEZE(X)) to BRCOND(X).
// Conservatively optimize integer comparisons only.
if (PreferSetCC) {
// Do this only when SETCC is going to be used by BRCOND.
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
bool Updated = false;
// Is 'X Cond C' always true or false?
auto IsAlwaysTrueOrFalse = [](ISD::CondCode Cond, ConstantSDNode *C) {
bool False = (Cond == ISD::SETULT && C->isNullValue()) ||
(Cond == ISD::SETLT && C->isMinSignedValue()) ||
(Cond == ISD::SETUGT && C->isAllOnesValue()) ||
(Cond == ISD::SETGT && C->isMaxSignedValue());
bool True = (Cond == ISD::SETULE && C->isAllOnesValue()) ||
(Cond == ISD::SETLE && C->isMaxSignedValue()) ||
(Cond == ISD::SETUGE && C->isNullValue()) ||
(Cond == ISD::SETGE && C->isMinSignedValue());
return True || False;
};
if (N0->getOpcode() == ISD::FREEZE && N0.hasOneUse() && N1C) {
if (!IsAlwaysTrueOrFalse(Cond, N1C)) {
N0 = N0->getOperand(0);
Updated = true;
}
}
if (N1->getOpcode() == ISD::FREEZE && N1.hasOneUse() && N0C) {
if (!IsAlwaysTrueOrFalse(ISD::getSetCCSwappedOperands(Cond),
N0C)) {
N1 = N1->getOperand(0);
Updated = true;
}
}
if (Updated)
return DAG.getFreeze(DAG.getSetCC(SDLoc(N), VT, N0, N1, Cond));
}
SDValue Combined = SimplifySetCC(VT, N->getOperand(0), N->getOperand(1), Cond,
SDLoc(N), !PreferSetCC);
if (!Combined)
return SDValue();

View File

@ -4,9 +4,7 @@
define i32 @f(i16* %p) {
; CHECK-LABEL: f:
; CHECK: # %bb.0:
; CHECK-NEXT: movzwl (%rdi), %eax
; CHECK-NEXT: andl $2048, %eax # imm = 0x800
; CHECK-NEXT: testw %ax, %ax
; CHECK-NEXT: testb $8, 1(%rdi)
; CHECK-NEXT: je .LBB0_1
; CHECK-NEXT: # %bb.2: # %B
; CHECK-NEXT: movl $20, %eax