Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -371,6 +371,8 @@ SDValue visitFFLOOR(SDNode *N); SDValue visitFMINNUM(SDNode *N); SDValue visitFMAXNUM(SDNode *N); + SDValue visitFMINNAN(SDNode *N); + SDValue visitFMAXNAN(SDNode *N); SDValue visitBRCOND(SDNode *N); SDValue visitBR_CC(SDNode *N); SDValue visitLOAD(SDNode *N); @@ -1582,6 +1584,8 @@ case ISD::FFLOOR: return visitFFLOOR(N); case ISD::FMINNUM: return visitFMINNUM(N); case ISD::FMAXNUM: return visitFMAXNUM(N); + case ISD::FMINNAN: return visitFMINNAN(N); + case ISD::FMAXNAN: return visitFMAXNAN(N); case ISD::FCEIL: return visitFCEIL(N); case ISD::FTRUNC: return visitFTRUNC(N); case ISD::BRCOND: return visitBRCOND(N); @@ -12124,7 +12128,8 @@ return SDValue(); } -SDValue DAGCombiner::visitFMINNUM(SDNode *N) { +static SDValue visitFMinMax(SelectionDAG &DAG, SDNode *N, + APFloat (*Op)(const APFloat &, const APFloat &)) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT VT = N->getValueType(0); @@ -12134,36 +12139,31 @@ if (N0CFP && N1CFP) { const APFloat &C0 = N0CFP->getValueAPF(); const APFloat &C1 = N1CFP->getValueAPF(); - return DAG.getConstantFP(minnum(C0, C1), SDLoc(N), VT); + return DAG.getConstantFP(Op(C0, C1), SDLoc(N), VT); } // Canonicalize to constant on RHS. if (isConstantFPBuildVectorOrConstantFP(N0) && - !isConstantFPBuildVectorOrConstantFP(N1)) - return DAG.getNode(ISD::FMINNUM, SDLoc(N), VT, N1, N0); + !isConstantFPBuildVectorOrConstantFP(N1)) + return DAG.getNode(N->getOpcode(), SDLoc(N), VT, N1, N0); return SDValue(); } -SDValue DAGCombiner::visitFMAXNUM(SDNode *N) { - SDValue N0 = N->getOperand(0); - SDValue N1 = N->getOperand(1); - EVT VT = N->getValueType(0); - const ConstantFPSDNode *N0CFP = isConstOrConstSplatFP(N0); - const ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1); +SDValue DAGCombiner::visitFMINNUM(SDNode *N) { + return visitFMinMax(DAG, N, minnum); +} - if (N0CFP && N1CFP) { - const APFloat &C0 = N0CFP->getValueAPF(); - const APFloat &C1 = N1CFP->getValueAPF(); - return DAG.getConstantFP(maxnum(C0, C1), SDLoc(N), VT); - } +SDValue DAGCombiner::visitFMAXNUM(SDNode *N) { + return visitFMinMax(DAG, N, maxnum); +} - // Canonicalize to constant on RHS. - if (isConstantFPBuildVectorOrConstantFP(N0) && - !isConstantFPBuildVectorOrConstantFP(N1)) - return DAG.getNode(ISD::FMAXNUM, SDLoc(N), VT, N1, N0); +SDValue DAGCombiner::visitFMINNAN(SDNode *N) { + return visitFMinMax(DAG, N, minimum); +} - return SDValue(); +SDValue DAGCombiner::visitFMAXNAN(SDNode *N) { + return visitFMinMax(DAG, N, maximum); } SDValue DAGCombiner::visitFABS(SDNode *N) { Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -824,7 +824,7 @@ ; SIMD128-NEXT: .result v128{{$}} ; SIMD128-NEXT: f32.const $push[[L0:[0-9]+]]=, 0x1.4p2 ; SIMD128-NEXT: f32x4.splat $push[[L1:[0-9]+]]=, $pop[[L0]] -; SIMD128-NEXT: f32x4.min $push[[R:[0-9]+]]=, $pop[[L1]], $0{{$}} +; SIMD128-NEXT: f32x4.min $push[[R:[0-9]+]]=, $0, $pop[[L1]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define <4 x float> @min_ordered_v4f32(<4 x float> %x) { %cmps = fcmp ole <4 x float> , %x @@ -839,7 +839,7 @@ ; SIMD128-NEXT: .result v128{{$}} ; SIMD128-NEXT: f32.const $push[[L0:[0-9]+]]=, 0x1.4p2 ; SIMD128-NEXT: f32x4.splat $push[[L1:[0-9]+]]=, $pop[[L0]] -; SIMD128-NEXT: f32x4.max $push[[R:[0-9]+]]=, $pop[[L1]], $0{{$}} +; SIMD128-NEXT: f32x4.max $push[[R:[0-9]+]]=, $0, $pop[[L1]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define <4 x float> @max_ordered_v4f32(<4 x float> %x) { %cmps = fcmp oge <4 x float> , %x @@ -872,6 +872,34 @@ ret <4 x float> %a } +; CHECK-LABEL: min_const_intrinsic_v4f32: +; NO-SIMD128-NOT: f32x4 +; SIMD128-NEXT: .result v128{{$}} +; SIMD128-NEXT: f32.const $push[[L:[0-9]+]]=, 0x1.4p2{{$}} +; SIMD128-NEXT: f32x4.splat $push[[R:[0-9]+]]=, $pop[[L]]{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @min_const_intrinsic_v4f32() { + %a = call <4 x float> @llvm.minimum.v4f32( + <4 x float> , + <4 x float> + ) + ret <4 x float> %a +} + +; CHECK-LABEL: max_const_intrinsic_v4f32: +; NO-SIMD128-NOT: f32x4 +; SIMD128-NEXT: .result v128{{$}} +; SIMD128-NEXT: f32.const $push[[L:[0-9]+]]=, 0x1.5p5{{$}} +; SIMD128-NEXT: f32x4.splat $push[[R:[0-9]+]]=, $pop[[L]]{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @max_const_intrinsic_v4f32() { + %a = call <4 x float> @llvm.maximum.v4f32( + <4 x float> , + <4 x float> + ) + ret <4 x float> %a +} + ; CHECK-LABEL: add_v4f32: ; NO-SIMD128-NOT: f32x4 ; SIMD128-NEXT: .param v128, v128{{$}} @@ -991,7 +1019,7 @@ ; SIMD128-NEXT: .result v128{{$}} ; SIMD128-NEXT: f64.const $push[[L0:[0-9]+]]=, 0x1.4p2 ; SIMD128-NEXT: f64x2.splat $push[[L1:[0-9]+]]=, $pop[[L0]] -; SIMD128-NEXT: f64x2.min $push[[R:[0-9]+]]=, $pop[[L1]], $0{{$}} +; SIMD128-NEXT: f64x2.min $push[[R:[0-9]+]]=, $0, $pop[[L1]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define <2 x double> @min_ordered_v2f64(<2 x double> %x) { %cmps = fcmp ole <2 x double> , %x @@ -1006,7 +1034,7 @@ ; SIMD128-NEXT: .result v128{{$}} ; SIMD128-NEXT: f64.const $push[[L0:[0-9]+]]=, 0x1.4p2 ; SIMD128-NEXT: f64x2.splat $push[[L1:[0-9]+]]=, $pop[[L0]] -; SIMD128-NEXT: f64x2.max $push[[R:[0-9]+]]=, $pop[[L1]], $0{{$}} +; SIMD128-NEXT: f64x2.max $push[[R:[0-9]+]]=, $0, $pop[[L1]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define <2 x double> @max_ordered_v2f64(<2 x double> %x) { %cmps = fcmp oge <2 x double> , %x @@ -1039,6 +1067,34 @@ ret <2 x double> %a } +; CHECK-LABEL: min_const_intrinsic_v2f64: +; NO-SIMD128-NOT: f64x2 +; SIMD128-NEXT: .result v128{{$}} +; SIMD128-NEXT: f64.const $push[[L:[0-9]+]]=, 0x1.4p2{{$}} +; SIMD128-NEXT: f64x2.splat $push[[R:[0-9]+]]=, $pop[[L]]{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @min_const_intrinsic_v2f64() { + %a = call <2 x double> @llvm.minimum.v2f64( + <2 x double> , + <2 x double> + ) + ret <2 x double> %a +} + +; CHECK-LABEL: max_const_intrinsic_v2f64: +; NO-SIMD128-NOT: f64x2 +; SIMD128-NEXT: .result v128{{$}} +; SIMD128-NEXT: f64.const $push[[L:[0-9]+]]=, 0x1.5p5{{$}} +; SIMD128-NEXT: f64x2.splat $push[[R:[0-9]+]]=, $pop[[L]]{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @max_const_intrinsic_v2f64() { + %a = call <2 x double> @llvm.maximum.v2f64( + <2 x double> , + <2 x double> + ) + ret <2 x double> %a +} + ; CHECK-LABEL: add_v2f64: ; NO-SIMD128-NOT: f64x2 ; SIMD128-VM-NOT: f62x2