diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3131,6 +3131,7 @@ Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT; bool IsUnaryAbs = false; + bool Negate = false; SDNodeFlags Flags; if (auto *FPOp = dyn_cast(&I)) @@ -3195,12 +3196,13 @@ break; } break; + case SPF_NABS: + Negate = true; + LLVM_FALLTHROUGH; case SPF_ABS: IsUnaryAbs = true; Opc = ISD::ABS; break; - case SPF_NABS: - // TODO: we need to produce sub(0, abs(X)). default: break; } @@ -3227,10 +3229,13 @@ if (IsUnaryAbs) { for (unsigned i = 0; i != NumValues; ++i) { + SDLoc dl = getCurSDLoc(); + EVT VT = LHSVal.getNode()->getValueType(LHSVal.getResNo() + i); Values[i] = - DAG.getNode(OpCode, getCurSDLoc(), - LHSVal.getNode()->getValueType(LHSVal.getResNo() + i), - SDValue(LHSVal.getNode(), LHSVal.getResNo() + i)); + DAG.getNode(OpCode, dl, VT, LHSVal.getValue(LHSVal.getResNo() + i)); + if (Negate) + Values[i] = DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT), + Values[i]); } } else { for (unsigned i = 0; i != NumValues; ++i) { 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 @@ -166,20 +158,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 @@ -219,21 +209,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 diff --git a/llvm/test/CodeGen/RISCV/neg-abs.ll b/llvm/test/CodeGen/RISCV/neg-abs.ll --- a/llvm/test/CodeGen/RISCV/neg-abs.ll +++ b/llvm/test/CodeGen/RISCV/neg-abs.ll @@ -27,19 +27,16 @@ define i32 @select_neg_abs32(i32 %x) { ; RV32-LABEL: select_neg_abs32: ; RV32: # %bb.0: -; RV32-NEXT: bltz a0, .LBB1_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: neg a0, a0 -; RV32-NEXT: .LBB1_2: +; RV32-NEXT: srai a1, a0, 31 +; RV32-NEXT: xor a0, a0, a1 +; RV32-NEXT: sub a0, a1, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: select_neg_abs32: ; RV64: # %bb.0: -; RV64-NEXT: sext.w a1, a0 -; RV64-NEXT: bltz a1, .LBB1_2 -; RV64-NEXT: # %bb.1: -; RV64-NEXT: negw a0, a0 -; RV64-NEXT: .LBB1_2: +; RV64-NEXT: sraiw a1, a0, 31 +; RV64-NEXT: xor a0, a0, a1 +; RV64-NEXT: subw a0, a1, a0 ; RV64-NEXT: ret %1 = icmp slt i32 %x, 0 %2 = sub nsw i32 0, %x @@ -73,21 +70,20 @@ define i64 @select_neg_abs64(i64 %x) { ; RV32-LABEL: select_neg_abs64: ; RV32: # %bb.0: -; RV32-NEXT: bltz a1, .LBB3_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: snez a2, a0 -; RV32-NEXT: add a1, a1, a2 -; RV32-NEXT: neg a1, a1 -; RV32-NEXT: neg a0, a0 -; RV32-NEXT: .LBB3_2: +; RV32-NEXT: srai a2, a1, 31 +; RV32-NEXT: xor a0, a0, a2 +; RV32-NEXT: sltu a3, a2, a0 +; RV32-NEXT: xor a1, a1, a2 +; RV32-NEXT: sub a1, a2, a1 +; RV32-NEXT: sub a1, a1, a3 +; RV32-NEXT: sub a0, a2, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: select_neg_abs64: ; RV64: # %bb.0: -; RV64-NEXT: bltz a0, .LBB3_2 -; RV64-NEXT: # %bb.1: -; RV64-NEXT: neg a0, a0 -; RV64-NEXT: .LBB3_2: +; RV64-NEXT: srai a1, a0, 63 +; RV64-NEXT: xor a0, a0, a1 +; RV64-NEXT: sub a0, a1, a0 ; RV64-NEXT: ret %1 = icmp slt i64 %x, 0 %2 = sub nsw i64 0, %x