summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp55
1 files changed, 47 insertions, 8 deletions
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