forked from OSchip/llvm-project
[DAGCombine][PowerPC] Simplify nabs by using legal `smin` operation
Convert `0 - abs(x)` to `smin (x, -x)` if `smin` is a legal operation. Verification: https://alive2.llvm.org/ce/z/vpquFR Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D92637
This commit is contained in:
parent
49599cb1a2
commit
44bd8ea167
|
@ -4393,8 +4393,10 @@ public:
|
||||||
/// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size))
|
/// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size))
|
||||||
/// \param N Node to expand
|
/// \param N Node to expand
|
||||||
/// \param Result output after conversion
|
/// \param Result output after conversion
|
||||||
|
/// \param IsNegative indicate negated abs
|
||||||
/// \returns True, if the expansion was successful, false otherwise
|
/// \returns True, if the expansion was successful, false otherwise
|
||||||
bool expandABS(SDNode *N, SDValue &Result, SelectionDAG &DAG) const;
|
bool expandABS(SDNode *N, SDValue &Result, SelectionDAG &DAG,
|
||||||
|
bool IsNegative = false) const;
|
||||||
|
|
||||||
/// Turn load of vector type into a load of the individual elements.
|
/// Turn load of vector type into a load of the individual elements.
|
||||||
/// \param LD load to expand
|
/// \param LD load to expand
|
||||||
|
|
|
@ -3193,18 +3193,12 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
|
||||||
return N1;
|
return N1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert 0 - abs(x) -> Y = sra (X, size(X)-1); sub (Y, xor (X, Y)).
|
// Convert 0 - abs(x).
|
||||||
|
SDValue Result;
|
||||||
if (N1->getOpcode() == ISD::ABS &&
|
if (N1->getOpcode() == ISD::ABS &&
|
||||||
!TLI.isOperationLegalOrCustom(ISD::ABS, VT)) {
|
!TLI.isOperationLegalOrCustom(ISD::ABS, VT) &&
|
||||||
SDValue X = N1->getOperand(0);
|
TLI.expandABS(N1.getNode(), Result, DAG, true))
|
||||||
SDValue Shift =
|
return Result;
|
||||||
DAG.getNode(ISD::SRA, DL, VT, X,
|
|
||||||
DAG.getConstant(BitWidth - 1, DL, getShiftAmountTy(VT)));
|
|
||||||
SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, X, Shift);
|
|
||||||
AddToWorklist(Shift.getNode());
|
|
||||||
AddToWorklist(Xor.getNode());
|
|
||||||
return DAG.getNode(ISD::SUB, DL, VT, Shift, Xor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1)
|
// Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1)
|
||||||
|
|
|
@ -6816,14 +6816,15 @@ bool TargetLowering::expandCTTZ(SDNode *Node, SDValue &Result,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TargetLowering::expandABS(SDNode *N, SDValue &Result,
|
bool TargetLowering::expandABS(SDNode *N, SDValue &Result,
|
||||||
SelectionDAG &DAG) const {
|
SelectionDAG &DAG, bool IsNegative) const {
|
||||||
SDLoc dl(N);
|
SDLoc dl(N);
|
||||||
EVT VT = N->getValueType(0);
|
EVT VT = N->getValueType(0);
|
||||||
EVT ShVT = getShiftAmountTy(VT, DAG.getDataLayout());
|
EVT ShVT = getShiftAmountTy(VT, DAG.getDataLayout());
|
||||||
SDValue Op = N->getOperand(0);
|
SDValue Op = N->getOperand(0);
|
||||||
|
|
||||||
// abs(x) -> smax(x,sub(0,x))
|
// abs(x) -> smax(x,sub(0,x))
|
||||||
if (isOperationLegal(ISD::SUB, VT) && isOperationLegal(ISD::SMAX, VT)) {
|
if (!IsNegative && isOperationLegal(ISD::SUB, VT) &&
|
||||||
|
isOperationLegal(ISD::SMAX, VT)) {
|
||||||
SDValue Zero = DAG.getConstant(0, dl, VT);
|
SDValue Zero = DAG.getConstant(0, dl, VT);
|
||||||
Result = DAG.getNode(ISD::SMAX, dl, VT, Op,
|
Result = DAG.getNode(ISD::SMAX, dl, VT, Op,
|
||||||
DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
|
DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
|
||||||
|
@ -6831,24 +6832,42 @@ bool TargetLowering::expandABS(SDNode *N, SDValue &Result,
|
||||||
}
|
}
|
||||||
|
|
||||||
// abs(x) -> umin(x,sub(0,x))
|
// abs(x) -> umin(x,sub(0,x))
|
||||||
if (isOperationLegal(ISD::SUB, VT) && isOperationLegal(ISD::UMIN, VT)) {
|
if (!IsNegative && isOperationLegal(ISD::SUB, VT) &&
|
||||||
|
isOperationLegal(ISD::UMIN, VT)) {
|
||||||
SDValue Zero = DAG.getConstant(0, dl, VT);
|
SDValue Zero = DAG.getConstant(0, dl, VT);
|
||||||
Result = DAG.getNode(ISD::UMIN, dl, VT, Op,
|
Result = DAG.getNode(ISD::UMIN, dl, VT, Op,
|
||||||
DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
|
DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0 - abs(x) -> smin(x, sub(0,x))
|
||||||
|
if (IsNegative && isOperationLegal(ISD::SUB, VT) &&
|
||||||
|
isOperationLegal(ISD::SMIN, VT)) {
|
||||||
|
SDValue Zero = DAG.getConstant(0, dl, VT);
|
||||||
|
Result = DAG.getNode(ISD::SMIN, dl, VT, Op,
|
||||||
|
DAG.getNode(ISD::SUB, dl, VT, Zero, Op));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Only expand vector types if we have the appropriate vector operations.
|
// Only expand vector types if we have the appropriate vector operations.
|
||||||
if (VT.isVector() && (!isOperationLegalOrCustom(ISD::SRA, VT) ||
|
if (VT.isVector() &&
|
||||||
!isOperationLegalOrCustom(ISD::ADD, VT) ||
|
(!isOperationLegalOrCustom(ISD::SRA, VT) ||
|
||||||
|
(!IsNegative && !isOperationLegalOrCustom(ISD::ADD, VT)) ||
|
||||||
|
(IsNegative && !isOperationLegalOrCustom(ISD::SUB, VT)) ||
|
||||||
!isOperationLegalOrCustomOrPromote(ISD::XOR, VT)))
|
!isOperationLegalOrCustomOrPromote(ISD::XOR, VT)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SDValue Shift =
|
SDValue Shift =
|
||||||
DAG.getNode(ISD::SRA, dl, VT, Op,
|
DAG.getNode(ISD::SRA, dl, VT, Op,
|
||||||
DAG.getConstant(VT.getScalarSizeInBits() - 1, dl, ShVT));
|
DAG.getConstant(VT.getScalarSizeInBits() - 1, dl, ShVT));
|
||||||
|
if (!IsNegative) {
|
||||||
SDValue Add = DAG.getNode(ISD::ADD, dl, VT, Op, Shift);
|
SDValue Add = DAG.getNode(ISD::ADD, dl, VT, Op, Shift);
|
||||||
Result = DAG.getNode(ISD::XOR, dl, VT, Add, Shift);
|
Result = DAG.getNode(ISD::XOR, dl, VT, Add, Shift);
|
||||||
|
} else {
|
||||||
|
// 0 - abs(x) -> Y = sra (X, size(X)-1); sub (Y, xor (X, Y))
|
||||||
|
SDValue Xor = DAG.getNode(ISD::XOR, dl, VT, Op, Shift);
|
||||||
|
Result = DAG.getNode(ISD::SUB, dl, VT, Shift, Xor);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,9 @@ define i64@neg_abs(i64 %x) {
|
||||||
define <2 x i64> @neg_abs_v2i64(<2 x i64> %0) {
|
define <2 x i64> @neg_abs_v2i64(<2 x i64> %0) {
|
||||||
; CHECK-LE-LABEL: neg_abs_v2i64:
|
; CHECK-LE-LABEL: neg_abs_v2i64:
|
||||||
; CHECK-LE: # %bb.0:
|
; CHECK-LE: # %bb.0:
|
||||||
; CHECK-LE-NEXT: addis r3, r2, .LCPI1_0@toc@ha
|
; CHECK-LE-NEXT: xxlxor vs35, vs35, vs35
|
||||||
; CHECK-LE-NEXT: addi r3, r3, .LCPI1_0@toc@l
|
; CHECK-LE-NEXT: vsubudm v3, v3, v2
|
||||||
; CHECK-LE-NEXT: lxvd2x vs0, 0, r3
|
; CHECK-LE-NEXT: vminsd v2, v2, v3
|
||||||
; CHECK-LE-NEXT: xxswapd vs35, vs0
|
|
||||||
; CHECK-LE-NEXT: vsrad v3, v2, v3
|
|
||||||
; CHECK-LE-NEXT: xxlxor vs34, vs34, vs35
|
|
||||||
; CHECK-LE-NEXT: vsubudm v2, v3, v2
|
|
||||||
; CHECK-LE-NEXT: blr
|
; CHECK-LE-NEXT: blr
|
||||||
%abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %0, i1 true)
|
%abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %0, i1 true)
|
||||||
%neg.abs = sub <2 x i64> zeroinitializer, %abs
|
%neg.abs = sub <2 x i64> zeroinitializer, %abs
|
||||||
|
@ -40,12 +36,9 @@ define <2 x i64> @neg_abs_v2i64(<2 x i64> %0) {
|
||||||
define <4 x i32> @neg_abs_v4i32(<4 x i32> %0) {
|
define <4 x i32> @neg_abs_v4i32(<4 x i32> %0) {
|
||||||
; CHECK-LE-LABEL: neg_abs_v4i32:
|
; CHECK-LE-LABEL: neg_abs_v4i32:
|
||||||
; CHECK-LE: # %bb.0:
|
; CHECK-LE: # %bb.0:
|
||||||
; CHECK-LE-NEXT: vspltisw v3, -16
|
; CHECK-LE-NEXT: xxlxor vs35, vs35, vs35
|
||||||
; CHECK-LE-NEXT: vspltisw v4, 15
|
; CHECK-LE-NEXT: vsubuwm v3, v3, v2
|
||||||
; CHECK-LE-NEXT: vsubuwm v3, v4, v3
|
; CHECK-LE-NEXT: vminsw v2, v2, v3
|
||||||
; CHECK-LE-NEXT: vsraw v3, v2, v3
|
|
||||||
; CHECK-LE-NEXT: xxlxor vs34, vs34, vs35
|
|
||||||
; CHECK-LE-NEXT: vsubuwm v2, v3, v2
|
|
||||||
; CHECK-LE-NEXT: blr
|
; CHECK-LE-NEXT: blr
|
||||||
%abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %0, i1 true)
|
%abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %0, i1 true)
|
||||||
%neg.abs = sub <4 x i32> zeroinitializer, %abs
|
%neg.abs = sub <4 x i32> zeroinitializer, %abs
|
||||||
|
@ -55,10 +48,9 @@ define <4 x i32> @neg_abs_v4i32(<4 x i32> %0) {
|
||||||
define <8 x i16> @neg_abs_v8i16(<8 x i16> %0) {
|
define <8 x i16> @neg_abs_v8i16(<8 x i16> %0) {
|
||||||
; CHECK-LE-LABEL: neg_abs_v8i16:
|
; CHECK-LE-LABEL: neg_abs_v8i16:
|
||||||
; CHECK-LE: # %bb.0:
|
; CHECK-LE: # %bb.0:
|
||||||
; CHECK-LE-NEXT: vspltish v3, 15
|
; CHECK-LE-NEXT: xxlxor vs35, vs35, vs35
|
||||||
; CHECK-LE-NEXT: vsrah v3, v2, v3
|
; CHECK-LE-NEXT: vsubuhm v3, v3, v2
|
||||||
; CHECK-LE-NEXT: xxlxor vs34, vs34, vs35
|
; CHECK-LE-NEXT: vminsh v2, v2, v3
|
||||||
; CHECK-LE-NEXT: vsubuhm v2, v3, v2
|
|
||||||
; CHECK-LE-NEXT: blr
|
; CHECK-LE-NEXT: blr
|
||||||
%abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %0, i1 true)
|
%abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %0, i1 true)
|
||||||
%neg.abs = sub <8 x i16> zeroinitializer, %abs
|
%neg.abs = sub <8 x i16> zeroinitializer, %abs
|
||||||
|
@ -68,10 +60,9 @@ define <8 x i16> @neg_abs_v8i16(<8 x i16> %0) {
|
||||||
define <16 x i8> @neg_abs_v16i8(<16 x i8> %0) {
|
define <16 x i8> @neg_abs_v16i8(<16 x i8> %0) {
|
||||||
; CHECK-LE-LABEL: neg_abs_v16i8:
|
; CHECK-LE-LABEL: neg_abs_v16i8:
|
||||||
; CHECK-LE: # %bb.0:
|
; CHECK-LE: # %bb.0:
|
||||||
; CHECK-LE-NEXT: vspltisb v3, 7
|
; CHECK-LE-NEXT: xxlxor vs35, vs35, vs35
|
||||||
; CHECK-LE-NEXT: vsrab v3, v2, v3
|
; CHECK-LE-NEXT: vsububm v3, v3, v2
|
||||||
; CHECK-LE-NEXT: xxlxor vs34, vs34, vs35
|
; CHECK-LE-NEXT: vminsb v2, v2, v3
|
||||||
; CHECK-LE-NEXT: vsububm v2, v3, v2
|
|
||||||
; CHECK-LE-NEXT: blr
|
; CHECK-LE-NEXT: blr
|
||||||
%abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %0, i1 true)
|
%abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %0, i1 true)
|
||||||
%neg.abs = sub <16 x i8> zeroinitializer, %abs
|
%neg.abs = sub <16 x i8> zeroinitializer, %abs
|
||||||
|
|
Loading…
Reference in New Issue