Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 71 additions & 8 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18371,9 +18371,75 @@ ARMTargetLowering::PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const {
return SDValue();
}

static SDValue foldCMOVOfCMOV(SDNode *Op, SelectionDAG &DAG) {
// (cmov A, B, CC1, (cmov C, D, CC2, Flags))
// -> (cmov (cmov A, B, CC1, C), (cmov A, B, CC1, D), CC2, Flags)
SDValue L = Op->getOperand(0);
SDValue R = Op->getOperand(1);
ARMCC::CondCodes OpCC =
static_cast<ARMCC::CondCodes>(Op->getConstantOperandVal(2));

SDValue OpCmp = Op->getOperand(3);
if (OpCmp.getOpcode() != ARMISD::CMPZ && OpCmp.getOpcode() != ARMISD::CMP)
// Only looking at EQ and NE cases.
return SDValue();

SDValue CmpLHS = OpCmp.getOperand(0);
SDValue CmpRHS = OpCmp.getOperand(1);

if (CmpRHS.getOpcode() == ARMISD::CMOV)
std::swap(CmpLHS, CmpRHS);
else if (CmpLHS.getOpcode() != ARMISD::CMOV)
return SDValue();

SDValue X = CmpLHS->getOperand(0);
SDValue Y = CmpLHS->getOperand(1);
if (!isa<ConstantSDNode>(X) || !isa<ConstantSDNode>(Y) || X == Y)
return SDValue();

ConstantSDNode *CX = cast<ConstantSDNode>(X);
ConstantSDNode *CY = cast<ConstantSDNode>(Y);
if (CX->getAPIntValue() == CY->getAPIntValue())
return SDValue();

ARMCC::CondCodes CC =
static_cast<ARMCC::CondCodes>(CmpLHS->getConstantOperandVal(2));
SDValue CondFlags = CmpLHS->getOperand(3);

if (CmpRHS == Y) {
// If the compare uses the second constant, flip the condition.
// VERIFY: getOppositeCondition does the same flip as AArch64's
// getInvertedCondCode.
CC = ARMCC::getOppositeCondition(CC);
} else if (CmpRHS != X) {
return SDValue();
}

if (OpCC == ARMCC::NE) {
// Outer NE inverts the sense.
CC = ARMCC::getOppositeCondition(CC);
} else if (OpCC != ARMCC::EQ) {
return SDValue();
}

SDLoc DL(Op);
EVT VT = Op->getValueType(0);
// CMOV takes (falseVal, trueVal, CC, Flags). To match (CSEL L,R,CC), pass
// (R,L).
SDValue CCValue = DAG.getConstant(CC, DL, FlagsVT);
return DAG.getNode(ARMISD::CMOV, DL, VT, R, L, CCValue, CondFlags);
}

/// PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
SDValue
ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
// CMOV x, x, cc -> x
if (N->getOperand(0) == N->getOperand(1))
return N->getOperand(0);

if (SDValue R = foldCMOVOfCMOV(N, DAG))
return R;

SDValue Cmp = N->getOperand(3);
if (Cmp.getOpcode() != ARMISD::CMPZ)
// Only looking at EQ and NE cases.
Expand Down Expand Up @@ -19951,14 +20017,11 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
}
break;
case ARMISD::CMOV: {
// Bits are known zero/one if known on the LHS and RHS.
Known = DAG.computeKnownBits(Op.getOperand(0), Depth+1);
if (Known.isUnknown())
return;

KnownBits KnownRHS = DAG.computeKnownBits(Op.getOperand(1), Depth+1);
Known = Known.intersectWith(KnownRHS);
return;
KnownBits Known2;
Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
Known = Known.intersectWith(Known2);
break;
}
case ISD::INTRINSIC_W_CHAIN: {
Intrinsic::ID IntID =
Expand Down
28 changes: 12 additions & 16 deletions llvm/test/CodeGen/ARM/addsubo-legalization.ll
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,17 @@ define <2 x i1> @uaddo(ptr %ptr, ptr %ptr2) {
; CHECK-NEXT: vmov r4, r5, d17
; CHECK-NEXT: subs.w r3, lr, r3
; CHECK-NEXT: sbcs.w r2, r12, r2
; CHECK-NEXT: mov.w r3, #-1
; CHECK-NEXT: mov.w r2, #0
; CHECK-NEXT: it lo
; CHECK-NEXT: movlo r2, #1
; CHECK-NEXT: cmp r2, #0
; CHECK-NEXT: it ne
; CHECK-NEXT: movne.w r2, #-1
; CHECK-NEXT: subs r3, r4, r6
; CHECK-NEXT: sbcs.w r3, r5, r7
; CHECK-NEXT: it lo
; CHECK-NEXT: movlo r2, r3
; CHECK-NEXT: subs r6, r4, r6
; CHECK-NEXT: sbcs.w r7, r5, r7
; CHECK-NEXT: itt lo
; CHECK-NEXT: movlo r1, #1
; CHECK-NEXT: cmp r1, #0
; CHECK-NEXT: it ne
; CHECK-NEXT: movne.w r1, #-1
; CHECK-NEXT: movlo r1, r3
; CHECK-NEXT: vst1.64 {d16, d17}, [r0]
; CHECK-NEXT: mov r0, r2
; CHECK-NEXT: pop {r4, r5, r6, r7, pc}
Expand All @@ -59,19 +57,17 @@ define <2 x i1> @usubo(ptr %ptr, ptr %ptr2) {
; CHECK-NEXT: vmov r6, r7, d17
; CHECK-NEXT: subs.w r3, lr, r3
; CHECK-NEXT: sbcs.w r2, r12, r2
; CHECK-NEXT: mov.w r3, #-1
; CHECK-NEXT: mov.w r2, #0
; CHECK-NEXT: it lo
; CHECK-NEXT: movlo r2, #1
; CHECK-NEXT: cmp r2, #0
; CHECK-NEXT: it ne
; CHECK-NEXT: movne.w r2, #-1
; CHECK-NEXT: subs r3, r4, r6
; CHECK-NEXT: sbcs.w r3, r5, r7
; CHECK-NEXT: it lo
; CHECK-NEXT: movlo r2, r3
; CHECK-NEXT: subs r6, r4, r6
; CHECK-NEXT: sbcs.w r7, r5, r7
; CHECK-NEXT: itt lo
; CHECK-NEXT: movlo r1, #1
; CHECK-NEXT: cmp r1, #0
; CHECK-NEXT: it ne
; CHECK-NEXT: movne.w r1, #-1
; CHECK-NEXT: movlo r1, r3
; CHECK-NEXT: vst1.64 {d16, d17}, [r0]
; CHECK-NEXT: mov r0, r2
; CHECK-NEXT: pop {r4, r5, r6, r7, pc}
Expand Down
Loading