summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp19
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp55
2 files changed, 66 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index cdefa30ef4f..1c32a92ddad 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -3351,6 +3351,25 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
!DAG.isConstantIntBuildVectorOrConstantInt(N1))
return DAG.getNode(N->getOpcode(), SDLoc(N), VT, N1, N0);
+ // Is sign bits are zero, flip between UMIN/UMAX and SMIN/SMAX.
+ // Only do this if the current op isn't legal and the flipped is.
+ unsigned Opcode = N->getOpcode();
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (!TLI.isOperationLegal(Opcode, VT) &&
+ (N0.isUndef() || DAG.SignBitIsZero(N0)) &&
+ (N1.isUndef() || DAG.SignBitIsZero(N1))) {
+ unsigned AltOpcode;
+ switch (Opcode) {
+ case ISD::SMIN: AltOpcode = ISD::UMIN; break;
+ case ISD::SMAX: AltOpcode = ISD::UMAX; break;
+ case ISD::UMIN: AltOpcode = ISD::SMIN; break;
+ case ISD::UMAX: AltOpcode = ISD::SMAX; break;
+ default: llvm_unreachable("Unknown MINMAX opcode");
+ }
+ if (TLI.isOperationLegal(AltOpcode, VT))
+ return DAG.getNode(AltOpcode, SDLoc(N), VT, N0, N1);
+ }
+
return SDValue();
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index ac3d7b550ce..474142d82a0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -790,10 +790,12 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FABS, MVT::v2f64, Custom);
setOperationAction(ISD::FCOPYSIGN, MVT::v2f64, Custom);
- setOperationAction(ISD::SMAX, MVT::v8i16, Legal);
- setOperationAction(ISD::UMAX, MVT::v16i8, Legal);
- setOperationAction(ISD::SMIN, MVT::v8i16, Legal);
- setOperationAction(ISD::UMIN, MVT::v16i8, Legal);
+ for (auto VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64 }) {
+ setOperationAction(ISD::SMAX, VT, VT == MVT::v8i16 ? Legal : Custom);
+ setOperationAction(ISD::SMIN, VT, VT == MVT::v8i16 ? Legal : Custom);
+ setOperationAction(ISD::UMAX, VT, VT == MVT::v16i8 ? Legal : Custom);
+ setOperationAction(ISD::UMIN, VT, VT == MVT::v16i8 ? Legal : Custom);
+ }
setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8i16, Custom);
setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom);
@@ -1067,6 +1069,11 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::MULHU, MVT::v32i8, Custom);
setOperationAction(ISD::MULHS, MVT::v32i8, Custom);
+ setOperationAction(ISD::SMAX, MVT::v4i64, Custom);
+ setOperationAction(ISD::UMAX, MVT::v4i64, Custom);
+ setOperationAction(ISD::SMIN, MVT::v4i64, Custom);
+ setOperationAction(ISD::UMIN, MVT::v4i64, Custom);
+
for (auto VT : { MVT::v32i8, MVT::v16i16, MVT::v8i32 }) {
setOperationAction(ISD::ABS, VT, HasInt256 ? Legal : Custom);
setOperationAction(ISD::SMAX, VT, HasInt256 ? Legal : Custom);
@@ -22062,10 +22069,42 @@ static SDValue LowerABS(SDValue Op, SelectionDAG &DAG) {
}
static SDValue LowerMINMAX(SDValue Op, SelectionDAG &DAG) {
- assert(Op.getSimpleValueType().is256BitVector() &&
- Op.getSimpleValueType().isInteger() &&
- "Only handle AVX 256-bit vector integer operation");
- return Lower256IntArith(Op, DAG);
+ MVT VT = Op.getSimpleValueType();
+
+ // For AVX1 cases, split to use use legal ops (everything but v4i64).
+ if (VT.getScalarType() != MVT::i64 && VT.is256BitVector())
+ return Lower256IntArith(Op, DAG);
+
+ SDLoc DL(Op);
+ unsigned Opcode = Op.getOpcode();
+ SDValue N0 = Op.getOperand(0);
+ SDValue N1 = Op.getOperand(1);
+
+ // For pre-SSE41, we can perform UMIN/UMAX v8i16 by flipping the signbit,
+ // using the SMIN/SMAX instructions and flipping the signbit back.
+ if (VT == MVT::v8i16) {
+ assert((Opcode == ISD::UMIN || Opcode == ISD::UMAX) &&
+ "Unexpected MIN/MAX opcode");
+ SDValue Sign = DAG.getConstant(APInt::getSignedMinValue(16), DL, VT);
+ N0 = DAG.getNode(ISD::XOR, DL, VT, N0, Sign);
+ N1 = DAG.getNode(ISD::XOR, DL, VT, N1, Sign);
+ Opcode = (Opcode == ISD::UMIN ? ISD::SMIN : ISD::SMAX);
+ SDValue Result = DAG.getNode(Opcode, DL, VT, N0, N1);
+ return DAG.getNode(ISD::XOR, DL, VT, Result, Sign);
+ }
+
+ // Else, expand to a compare/select.
+ ISD::CondCode CC;
+ switch (Opcode) {
+ case ISD::SMIN: CC = ISD::CondCode::SETLT; break;
+ case ISD::SMAX: CC = ISD::CondCode::SETGT; break;
+ case ISD::UMIN: CC = ISD::CondCode::SETULT; break;
+ case ISD::UMAX: CC = ISD::CondCode::SETUGT; break;
+ default: llvm_unreachable("Unknown MINMAX opcode");
+ }
+
+ SDValue Cond = DAG.getSetCC(DL, VT, N0, N1, CC);
+ return DAG.getSelect(DL, VT, Cond, N0, N1);
}
static SDValue LowerMUL(SDValue Op, const X86Subtarget &Subtarget,
OpenPOWER on IntegriCloud