Skip to content

Commit 4f71f59

Browse files
committed
[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
1 parent 784f258 commit 4f71f59

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,8 @@ class ConstantSDNode : public SDNode {
15651565
bool isOne() const { return Value->isOne(); }
15661566
bool isNullValue() const { return Value->isZero(); }
15671567
bool isAllOnesValue() const { return Value->isMinusOne(); }
1568+
bool isMaxSignedValue() const { return Value->isMaxValue(true); }
1569+
bool isMinSignedValue() const { return Value->isMinValue(true); }
15681570

15691571
bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }
15701572

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10223,9 +10223,62 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
1022310223
bool PreferSetCC =
1022410224
N->hasOneUse() && N->use_begin()->getOpcode() == ISD::BRCOND;
1022510225

10226-
SDValue Combined = SimplifySetCC(
10227-
N->getValueType(0), N->getOperand(0), N->getOperand(1),
10228-
cast<CondCodeSDNode>(N->getOperand(2))->get(), SDLoc(N), !PreferSetCC);
10226+
ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
10227+
EVT VT = N->getValueType(0);
10228+
10229+
// SETCC(FREEZE(X), CONST, Cond)
10230+
// =>
10231+
// FREEZE(SETCC(X, CONST, Cond))
10232+
// This is correct if FREEZE(X) has one use and SETCC(FREEZE(X), CONST, Cond)
10233+
// isn't equivalent to true or false.
10234+
// For example, SETCC(FREEZE(X), -128, SETULT) cannot be folded to
10235+
// FREEZE(SETCC(X, -128, SETULT)) because X can be poison.
10236+
//
10237+
// This transformation is beneficial because visitBRCOND can fold
10238+
// BRCOND(FREEZE(X)) to BRCOND(X).
10239+
10240+
// Conservatively optimize integer comparisons only.
10241+
if (PreferSetCC) {
10242+
// Do this only when SETCC is going to be used by BRCOND.
10243+
10244+
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
10245+
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
10246+
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
10247+
bool Updated = false;
10248+
10249+
// Is 'X Cond C' always true or false?
10250+
auto IsAlwaysTrueOrFalse = [](ISD::CondCode Cond, ConstantSDNode *C) {
10251+
bool False = (Cond == ISD::SETULT && C->isNullValue()) ||
10252+
(Cond == ISD::SETLT && C->isMinSignedValue()) ||
10253+
(Cond == ISD::SETUGT && C->isAllOnesValue()) ||
10254+
(Cond == ISD::SETGT && C->isMaxSignedValue());
10255+
bool True = (Cond == ISD::SETULE && C->isAllOnesValue()) ||
10256+
(Cond == ISD::SETLE && C->isMaxSignedValue()) ||
10257+
(Cond == ISD::SETUGE && C->isNullValue()) ||
10258+
(Cond == ISD::SETGE && C->isMinSignedValue());
10259+
return True || False;
10260+
};
10261+
10262+
if (N0->getOpcode() == ISD::FREEZE && N0.hasOneUse() && N1C) {
10263+
if (!IsAlwaysTrueOrFalse(Cond, N1C)) {
10264+
N0 = N0->getOperand(0);
10265+
Updated = true;
10266+
}
10267+
}
10268+
if (N1->getOpcode() == ISD::FREEZE && N1.hasOneUse() && N0C) {
10269+
if (!IsAlwaysTrueOrFalse(ISD::getSetCCSwappedOperands(Cond),
10270+
N0C)) {
10271+
N1 = N1->getOperand(0);
10272+
Updated = true;
10273+
}
10274+
}
10275+
10276+
if (Updated)
10277+
return DAG.getFreeze(DAG.getSetCC(SDLoc(N), VT, N0, N1, Cond));
10278+
}
10279+
10280+
SDValue Combined = SimplifySetCC(VT, N->getOperand(0), N->getOperand(1), Cond,
10281+
SDLoc(N), !PreferSetCC);
1022910282

1023010283
if (!Combined)
1023110284
return SDValue();

llvm/test/CodeGen/X86/setcc-freeze.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
define i32 @f(i16* %p) {
55
; CHECK-LABEL: f:
66
; CHECK: # %bb.0:
7-
; CHECK-NEXT: movzwl (%rdi), %eax
8-
; CHECK-NEXT: andl $2048, %eax # imm = 0x800
9-
; CHECK-NEXT: testw %ax, %ax
7+
; CHECK-NEXT: testb $8, 1(%rdi)
108
; CHECK-NEXT: je .LBB0_1
119
; CHECK-NEXT: # %bb.2: # %B
1210
; CHECK-NEXT: movl $20, %eax

0 commit comments

Comments
 (0)