[ConstantFolding] add undef handling for fmin/fmax intrinsics
authorSanjay Patel <spatel@rotateright.com>
Fri, 18 Sep 2020 20:37:17 +0000 (16:37 -0400)
committerSanjay Patel <spatel@rotateright.com>
Sat, 19 Sep 2020 14:31:01 +0000 (10:31 -0400)
The output here may not be optimal (yet), but it should be
consistent for commuted operands (it was not before) and
correct. We can do better by checking FMF and NaN if needed.

Code in InstSimplify generally assumes that we have already
folded code like this, so it was not handling 2 constant
inputs by commuting consistently.

llvm/lib/Analysis/ConstantFolding.cpp
llvm/test/Transforms/InstSimplify/ConstProp/fp-undef.ll

index aaab600..0ddca5a 100644 (file)
@@ -2305,6 +2305,25 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
                                          const CallBase *Call) {
   assert(Operands.size() == 2 && "Wrong number of operands.");
 
+  if (Ty->isFloatingPointTy()) {
+    // TODO: We should have undef handling for all of the FP intrinsics that
+    //       are attempted to be folded in this function.
+    bool IsOp0Undef = isa<UndefValue>(Operands[0]);
+    bool IsOp1Undef = isa<UndefValue>(Operands[1]);
+    switch (IntrinsicID) {
+    case Intrinsic::maxnum:
+    case Intrinsic::minnum:
+    case Intrinsic::maximum:
+    case Intrinsic::minimum:
+      // If one argument is undef, return the other argument.
+      if (IsOp0Undef)
+        return Operands[1];
+      if (IsOp1Undef)
+        return Operands[0];
+      break;
+    }
+  }
+
   if (auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
     if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
       return nullptr;
index b77337a..fd139f0 100644 (file)
@@ -540,7 +540,7 @@ define <2 x double> @frem_undef_op0_constant_vec(<2 x double> %x) {
 
 define <2 x double> @maximum_nan_op0_vec_partial_undef_op1_undef(<2 x double> %x) {
 ; CHECK-LABEL: @maximum_nan_op0_vec_partial_undef_op1_undef(
-; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
 ;
   %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> undef)
   ret <2 x double> %r
@@ -556,7 +556,7 @@ define <2 x double> @maximum_nan_op1_vec_partial_undef_op0_undef(<2 x double> %x
 
 define <2 x double> @minimum_nan_op0_vec_partial_undef_op1_undef(<2 x double> %x) {
 ; CHECK-LABEL: @minimum_nan_op0_vec_partial_undef_op1_undef(
-; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
 ;
   %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> undef)
   ret <2 x double> %r
@@ -572,7 +572,7 @@ define <2 x double> @minimum_nan_op1_vec_partial_undef_op0_undef(<2 x double> %x
 
 define <2 x double> @maxnum_nan_op0_vec_partial_undef_op1_undef(<2 x double> %x) {
 ; CHECK-LABEL: @maxnum_nan_op0_vec_partial_undef_op1_undef(
-; CHECK-NEXT:    ret <2 x double> undef
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
 ;
   %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> undef)
   ret <2 x double> %r
@@ -588,7 +588,7 @@ define <2 x double> @maxnum_nan_op1_vec_partial_undef_op0_undef(<2 x double> %x)
 
 define <2 x double> @minnum_nan_op0_vec_partial_undef_op1_undef(<2 x double> %x) {
 ; CHECK-LABEL: @minnum_nan_op0_vec_partial_undef_op1_undef(
-; CHECK-NEXT:    ret <2 x double> undef
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
 ;
   %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> undef)
   ret <2 x double> %r