diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9326,6 +9326,31 @@ } } + // Fold integer negated abs. + // select (setg[te] X, 0), -X, X -> + // select (setgt X, -1), -X, X -> + // select (setl[te] X, 0), X, -X -> + // Y = sra (X, size(X)-1); sub (Y, xor (X, Y)) + if (N0.getOpcode() == ISD::SETCC) { + SDValue LHS = N0.getOperand(0); + SDValue RHS = N0.getOperand(1); + if (((((isNullConstant(RHS) && (CC == ISD::SETGT || CC == ISD::SETGE)) || + (isAllOnesConstant(RHS) && CC == ISD::SETGT)) && + N1.getOpcode() == ISD::SUB && isNullConstant(N1.getOperand(0)) && + LHS == N1.getOperand(1) && N2 == LHS)) || + (isNullConstant(RHS) && (CC == ISD::SETLT || CC == ISD::SETLE) && + N1 == LHS && N2.getOpcode() == ISD::SUB && + isNullConstant(N2.getOperand(0)) && LHS == N2.getOperand(1))) { + SDValue Shift = DAG.getNode( + ISD::SRA, DL, VT, LHS, + DAG.getConstant(VT.getSizeInBits() - 1, DL, getShiftAmountTy(VT))); + SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, LHS, Shift); + AddToWorklist(Shift.getNode()); + AddToWorklist(Xor.getNode()); + return DAG.getNode(ISD::SUB, DL, VT, Shift, Xor); + } + } + if (TLI.isOperationLegal(ISD::SELECT_CC, VT) || (!LegalOperations && TLI.isOperationLegalOrCustom(ISD::SELECT_CC, VT))) { diff --git a/llvm/test/CodeGen/PowerPC/select.ll b/llvm/test/CodeGen/PowerPC/select.ll --- a/llvm/test/CodeGen/PowerPC/select.ll +++ b/llvm/test/CodeGen/PowerPC/select.ll @@ -111,26 +111,18 @@ define i64 @f4(i64 %x) { ; CHECK-LE-LABEL: f4: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: neg r4, r3 -; CHECK-LE-NEXT: cmpdi r3, 0 -; CHECK-LE-NEXT: iselgt r3, r4, r3 +; CHECK-LE-NEXT: sradi r4, r3, 63 +; CHECK-LE-NEXT: xor r3, r3, r4 +; CHECK-LE-NEXT: sub r3, r4, r3 ; CHECK-LE-NEXT: blr ; ; CHECK-32-LABEL: f4: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: cmplwi r3, 0 -; CHECK-32-NEXT: cmpwi cr1, r3, 0 -; CHECK-32-NEXT: crandc 4*cr5+lt, 4*cr1+gt, eq -; CHECK-32-NEXT: cmpwi cr1, r4, 0 -; CHECK-32-NEXT: subfic r5, r4, 0 -; CHECK-32-NEXT: crandc 4*cr5+gt, eq, 4*cr1+eq -; CHECK-32-NEXT: cror 4*cr5+lt, 4*cr5+gt, 4*cr5+lt -; CHECK-32-NEXT: subfze r6, r3 -; CHECK-32-NEXT: bc 12, 4*cr5+lt, .LBB4_1 -; CHECK-32-NEXT: blr -; CHECK-32-NEXT: .LBB4_1: -; CHECK-32-NEXT: addi r3, r6, 0 -; CHECK-32-NEXT: addi r4, r5, 0 +; CHECK-32-NEXT: srawi r5, r3, 31 +; CHECK-32-NEXT: xor r4, r4, r5 +; CHECK-32-NEXT: xor r3, r3, r5 +; CHECK-32-NEXT: subc r4, r5, r4 +; CHECK-32-NEXT: subfe r3, r3, r5 ; CHECK-32-NEXT: blr %c = icmp sgt i64 %x, 0 %x.neg = sub i64 0, %x @@ -141,21 +133,18 @@ define i64 @f4_sge_0(i64 %x) { ; CHECK-LE-LABEL: f4_sge_0: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: neg r4, r3 -; CHECK-LE-NEXT: cmpdi r3, -1 -; CHECK-LE-NEXT: iselgt r3, r4, r3 +; CHECK-LE-NEXT: sradi r4, r3, 63 +; CHECK-LE-NEXT: xor r3, r3, r4 +; CHECK-LE-NEXT: sub r3, r4, r3 ; CHECK-LE-NEXT: blr ; ; CHECK-32-LABEL: f4_sge_0: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: subfic r5, r4, 0 -; CHECK-32-NEXT: subfze r6, r3 -; CHECK-32-NEXT: cmpwi r3, -1 -; CHECK-32-NEXT: bc 12, gt, .LBB5_1 -; CHECK-32-NEXT: blr -; CHECK-32-NEXT: .LBB5_1: -; CHECK-32-NEXT: addi r3, r6, 0 -; CHECK-32-NEXT: addi r4, r5, 0 +; CHECK-32-NEXT: srawi r5, r3, 31 +; CHECK-32-NEXT: xor r4, r4, r5 +; CHECK-32-NEXT: xor r3, r3, r5 +; CHECK-32-NEXT: subc r4, r5, r4 +; CHECK-32-NEXT: subfe r3, r3, r5 ; CHECK-32-NEXT: blr %c = icmp sge i64 %x, 0 %x.neg = sub i64 0, %x @@ -166,20 +155,18 @@ define i64 @f4_slt_0(i64 %x) { ; CHECK-LE-LABEL: f4_slt_0: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: neg r4, r3 -; CHECK-LE-NEXT: cmpdi r3, 0 -; CHECK-LE-NEXT: isellt r3, r3, r4 +; CHECK-LE-NEXT: sradi r4, r3, 63 +; CHECK-LE-NEXT: xor r3, r3, r4 +; CHECK-LE-NEXT: sub r3, r4, r3 ; CHECK-LE-NEXT: blr ; ; CHECK-32-LABEL: f4_slt_0: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: subfic r5, r4, 0 -; CHECK-32-NEXT: subfze r6, r3 -; CHECK-32-NEXT: cmpwi r3, 0 -; CHECK-32-NEXT: bclr 12, lt, 0 -; CHECK-32-NEXT: # %bb.1: -; CHECK-32-NEXT: ori r3, r6, 0 -; CHECK-32-NEXT: ori r4, r5, 0 +; CHECK-32-NEXT: srawi r5, r3, 31 +; CHECK-32-NEXT: xor r4, r4, r5 +; CHECK-32-NEXT: xor r3, r3, r5 +; CHECK-32-NEXT: subc r4, r5, r4 +; CHECK-32-NEXT: subfe r3, r3, r5 ; CHECK-32-NEXT: blr %c = icmp slt i64 %x, 0 %x.neg = sub i64 0, %x @@ -190,25 +177,18 @@ define i64 @f4_sle_0(i64 %x) { ; CHECK-LE-LABEL: f4_sle_0: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: neg r4, r3 -; CHECK-LE-NEXT: cmpdi r3, 1 -; CHECK-LE-NEXT: isellt r3, r3, r4 +; CHECK-LE-NEXT: sradi r4, r3, 63 +; CHECK-LE-NEXT: xor r3, r3, r4 +; CHECK-LE-NEXT: sub r3, r4, r3 ; CHECK-LE-NEXT: blr ; ; CHECK-32-LABEL: f4_sle_0: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: cmplwi r3, 0 -; CHECK-32-NEXT: cmpwi cr1, r3, 0 -; CHECK-32-NEXT: crandc 4*cr5+lt, 4*cr1+lt, eq -; CHECK-32-NEXT: cmpwi cr1, r4, 0 -; CHECK-32-NEXT: subfic r5, r4, 0 -; CHECK-32-NEXT: crand 4*cr5+gt, eq, 4*cr1+eq -; CHECK-32-NEXT: cror 4*cr5+lt, 4*cr5+gt, 4*cr5+lt -; CHECK-32-NEXT: subfze r6, r3 -; CHECK-32-NEXT: bclr 12, 4*cr5+lt, 0 -; CHECK-32-NEXT: # %bb.1: -; CHECK-32-NEXT: ori r3, r6, 0 -; CHECK-32-NEXT: ori r4, r5, 0 +; CHECK-32-NEXT: srawi r5, r3, 31 +; CHECK-32-NEXT: xor r4, r4, r5 +; CHECK-32-NEXT: xor r3, r3, r5 +; CHECK-32-NEXT: subc r4, r5, r4 +; CHECK-32-NEXT: subfe r3, r3, r5 ; CHECK-32-NEXT: blr %c = icmp sle i64 %x, 0 %x.neg = sub i64 0, %x @@ -219,21 +199,18 @@ define i64 @f4_sgt_m1(i64 %x) { ; CHECK-LE-LABEL: f4_sgt_m1: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: neg r4, r3 -; CHECK-LE-NEXT: cmpdi r3, -1 -; CHECK-LE-NEXT: iselgt r3, r4, r3 +; CHECK-LE-NEXT: sradi r4, r3, 63 +; CHECK-LE-NEXT: xor r3, r3, r4 +; CHECK-LE-NEXT: sub r3, r4, r3 ; CHECK-LE-NEXT: blr ; ; CHECK-32-LABEL: f4_sgt_m1: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: subfic r5, r4, 0 -; CHECK-32-NEXT: subfze r6, r3 -; CHECK-32-NEXT: cmpwi r3, -1 -; CHECK-32-NEXT: bc 12, gt, .LBB8_1 -; CHECK-32-NEXT: blr -; CHECK-32-NEXT: .LBB8_1: -; CHECK-32-NEXT: addi r3, r6, 0 -; CHECK-32-NEXT: addi r4, r5, 0 +; CHECK-32-NEXT: srawi r5, r3, 31 +; CHECK-32-NEXT: xor r4, r4, r5 +; CHECK-32-NEXT: xor r3, r3, r5 +; CHECK-32-NEXT: subc r4, r5, r4 +; CHECK-32-NEXT: subfe r3, r3, r5 ; CHECK-32-NEXT: blr %c = icmp sgt i64 %x, -1 %x.neg = sub i64 0, %x