diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 33fa3012618b3..65fd863e55ac9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -909,6 +909,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { SDValue ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N); SDValue ScalarizeVecOp_VSELECT(SDNode *N); SDValue ScalarizeVecOp_VSETCC(SDNode *N); + SDValue ScalarizeVecOp_VSTRICT_FSETCC(SDNode *N, unsigned OpNo); SDValue ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo); SDValue ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo); SDValue ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N, unsigned OpNo); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index bc2dbfb4cbaae..a0fd855832a33 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -789,6 +789,10 @@ bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) { case ISD::SETCC: Res = ScalarizeVecOp_VSETCC(N); break; + case ISD::STRICT_FSETCC: + case ISD::STRICT_FSETCCS: + Res = ScalarizeVecOp_VSTRICT_FSETCC(N, OpNo); + break; case ISD::STORE: Res = ScalarizeVecOp_STORE(cast(N), OpNo); break; @@ -985,6 +989,43 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) { return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res); } +// Similiar to ScalarizeVecOp_VSETCC, with added logic to update chains. +SDValue DAGTypeLegalizer::ScalarizeVecOp_VSTRICT_FSETCC(SDNode *N, + unsigned OpNo) { + assert(OpNo == 1 && "Wrong operand for scalarization!"); + assert(N->getValueType(0).isVector() && + N->getOperand(1).getValueType().isVector() && + "Operand types must be vectors"); + assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type"); + + EVT VT = N->getValueType(0); + SDValue Ch = N->getOperand(0); + SDValue LHS = GetScalarizedVector(N->getOperand(1)); + SDValue RHS = GetScalarizedVector(N->getOperand(2)); + SDValue CC = N->getOperand(3); + + EVT OpVT = N->getOperand(1).getValueType(); + EVT NVT = VT.getVectorElementType(); + SDLoc DL(N); + SDValue Res = DAG.getNode(N->getOpcode(), DL, {MVT::i1, MVT::Other}, + {Ch, LHS, RHS, CC}); + + // Legalize the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + + ISD::NodeType ExtendCode = + TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT)); + + Res = DAG.getNode(ExtendCode, DL, NVT, Res); + Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res); + + // Do our own replacement and return SDValue() to tell the caller that we + // handled all replacements since caller can only handle a single result. + ReplaceValueWith(SDValue(N, 0), Res); + return SDValue(); +} + /// If the value to store is a vector that needs to be scalarized, it must be /// <1 x ty>. Just store the element. SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ diff --git a/llvm/test/CodeGen/X86/fp80-strict-vec-cmp.ll b/llvm/test/CodeGen/X86/fp80-strict-vec-cmp.ll new file mode 100644 index 0000000000000..b4c77a573e859 --- /dev/null +++ b/llvm/test/CodeGen/X86/fp80-strict-vec-cmp.ll @@ -0,0 +1,293 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s + +define <1 x i1> @test_oeq_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_oeq_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %cl +; CHECK-NEXT: sete %al +; CHECK-NEXT: andb %cl, %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"oeq", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ogt_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ogt_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: seta %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ogt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_oge_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_oge_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setae %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"oge", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_olt_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_olt_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm0, %xmm1 +; CHECK-NEXT: seta %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"olt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ole_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ole_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm0, %xmm1 +; CHECK-NEXT: setae %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ole", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_one_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_one_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setne %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"one", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ord_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ord_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ord", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ueq_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ueq_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ord", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ugt_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ugt_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm0, %xmm1 +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ugt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_uge_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_uge_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm0, %xmm1 +; CHECK-NEXT: setbe %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"uge", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ult_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ult_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ult", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ule_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ule_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setbe %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ule", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_une_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_une_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setp %cl +; CHECK-NEXT: setne %al +; CHECK-NEXT: orb %cl, %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"une", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_uno_q_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_uno_q_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vucomisd %xmm1, %xmm0 +; CHECK-NEXT: setp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double> %a, <1 x double> %b, metadata !"uno", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_oeq_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_oeq_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %cl +; CHECK-NEXT: sete %al +; CHECK-NEXT: andb %cl, %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"oeq", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ogt_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ogt_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: seta %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ogt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_oge_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_oge_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setae %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"oge", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_olt_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_olt_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm0, %xmm1 +; CHECK-NEXT: seta %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"olt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ole_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ole_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm0, %xmm1 +; CHECK-NEXT: setae %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ole", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_one_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_one_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setne %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"one", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ord_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ord_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ord", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ueq_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ueq_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setnp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ord", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ugt_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ugt_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm0, %xmm1 +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ugt", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_uge_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_uge_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm0, %xmm1 +; CHECK-NEXT: setbe %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"uge", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ult_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ult_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ult", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_ule_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_ule_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setbe %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"ule", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_une_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_une_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setp %cl +; CHECK-NEXT: setne %al +; CHECK-NEXT: orb %cl, %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"une", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +define <1 x i1> @test_uno_s_v1f64(<1 x double> %a, <1 x double> %b) { +; CHECK-LABEL: test_uno_s_v1f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vcomisd %xmm1, %xmm0 +; CHECK-NEXT: setp %al +; CHECK-NEXT: retq + %cond = tail call <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double> %a, <1 x double> %b, metadata !"uno", metadata !"fpexcept.strict") + ret <1 x i1> %cond +} + +declare <1 x i1> @llvm.experimental.constrained.fcmp.v1f64(<1 x double>, <1 x double>, metadata, metadata) +declare <1 x i1> @llvm.experimental.constrained.fcmps.v1f64(<1 x double>, <1 x double>, metadata, metadata)