OSDN Git Service

[DAGCombine] foldBinOpIntoSelect can fail to constant fold in some cases.
authorSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 27 Dec 2017 11:36:18 +0000 (11:36 +0000)
committerSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 27 Dec 2017 11:36:18 +0000 (11:36 +0000)
For example, float operations may fail to constant fold under certain circumstances (inf/nan/denormal creation etc.)

Reduced from oss-fuzz #4802 test case

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321488 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
test/CodeGen/X86/fdiv-combine.ll

index 1119a36..3218dce 100644 (file)
@@ -1922,14 +1922,16 @@ SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
   EVT VT = Sel.getValueType();
   SDLoc DL(Sel);
   SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1);
-  assert((NewCT.isUndef() || isConstantOrConstantVector(NewCT) ||
-          isConstantFPBuildVectorOrConstantFP(NewCT)) &&
-         "Failed to constant fold a binop with constant operands");
+  if (!NewCT.isUndef() &&
+      !isConstantOrConstantVector(NewCT, true) &&
+      !isConstantFPBuildVectorOrConstantFP(NewCT))
+    return SDValue();
 
   SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1);
-  assert((NewCF.isUndef() || isConstantOrConstantVector(NewCF) ||
-          isConstantFPBuildVectorOrConstantFP(NewCF)) &&
-         "Failed to constant fold a binop with constant operands");
+  if (!NewCF.isUndef() &&
+      !isConstantOrConstantVector(NewCF, true) &&
+      !isConstantFPBuildVectorOrConstantFP(NewCF))
+    return SDValue();
 
   return DAG.getSelect(DL, VT, Sel.getOperand(0), NewCT, NewCF);
 }
index 912110e..62e86e3 100644 (file)
@@ -95,6 +95,41 @@ define double @div3_arcp(double %x, double %y, double %z) {
   ret double %ret
 }
 
+define float @div_select_constant_fold(i1 zeroext %arg) {
+; CHECK-LABEL: div_select_constant_fold:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    testl %edi, %edi
+; CHECK-NEXT:    jne .LBB6_1
+; CHECK-NEXT:  # %bb.2:
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    retq
+; CHECK-NEXT:  .LBB6_1:
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    retq
+  %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00
+  %B2 = fdiv float %tmp, 1.000000e+00
+  ret float %B2
+}
+
+define float @div_select_constant_fold_zero(i1 zeroext %arg) {
+; CHECK-LABEL: div_select_constant_fold_zero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    testl %edi, %edi
+; CHECK-NEXT:    jne .LBB7_1
+; CHECK-NEXT:  # %bb.2:
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    jmp .LBB7_3
+; CHECK-NEXT:  .LBB7_1:
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:  .LBB7_3:
+; CHECK-NEXT:    xorps %xmm1, %xmm1
+; CHECK-NEXT:    divss %xmm1, %xmm0
+; CHECK-NEXT:    retq
+  %tmp = select i1 %arg, float 5.000000e+00, float 6.000000e+00
+  %B2 = fdiv float %tmp, 0.000000e+00
+  ret float %B2
+}
+
 define void @PR24141() {
 ; CHECK-LABEL: PR24141:
 ; CHECK:       callq