diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13952,7 +13952,7 @@ // guaranteed-non-poison operands then push the freeze through to the one // operand that is not guaranteed non-poison. if (!DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false, - /*ConsiderFlags*/ true) && + /*ConsiderFlags*/ false) && N0->getNumValues() == 1 && N0->hasOneUse()) { SDValue MaybePoisonOperand; for (SDValue Op : N0->ops()) { @@ -13969,7 +13969,6 @@ } if (MaybePoisonOperand) { // Recreate the node with the frozen maybe-poison operand. - // TODO: Disable ConsiderFlags and just strip poison generating flags? // TODO: Drop the isOnlyUserOf constraint and replace all users of // MaybePoisonOperand with FrozenMaybePoisonOperand // to match pushFreezeToPreventPoisonFromPropagating behavior. @@ -13978,7 +13977,11 @@ for (SDValue &Op : Ops) if (Op == MaybePoisonOperand) Op = FrozenMaybePoisonOperand; - return DAG.getNode(N0.getOpcode(), SDLoc(N0), N0->getVTList(), Ops); + // TODO: Just strip poison generating flags? + SDValue R = DAG.getNode(N0.getOpcode(), SDLoc(N0), N0->getVTList(), Ops); + assert(DAG.isGuaranteedNotToBeUndefOrPoison(R, /*PoisonOnly*/ false) && + "Can't create node that may be undef/poison!"); + return R; } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4551,9 +4551,9 @@ } return true; - // TODO: Search for noundef attributes from library functions. + // TODO: Search for noundef attributes from library functions. - // TODO: Pointers dereferenced by ISD::LOAD/STORE ops are noundef. + // TODO: Pointers dereferenced by ISD::LOAD/STORE ops are noundef. default: // Allow the target to implement this method for its nodes. @@ -4564,7 +4564,15 @@ break; } - return false; + // If Op can't create undef/poison and none of its operands are undef/poison + // then Op is never undef/poison. + // NOTE: TargetNodes should handle this in themselves in + // isGuaranteedNotToBeUndefOrPoisonForTargetNode. + return !canCreateUndefOrPoison(Op, PoisonOnly, /*ConsiderFlags*/ true, + Depth) && + all_of(Op->ops(), [&](SDValue V) { + return isGuaranteedNotToBeUndefOrPoison(V, PoisonOnly, Depth + 1); + }); } bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, bool PoisonOnly, diff --git a/llvm/test/CodeGen/X86/freeze-binary.ll b/llvm/test/CodeGen/X86/freeze-binary.ll --- a/llvm/test/CodeGen/X86/freeze-binary.ll +++ b/llvm/test/CodeGen/X86/freeze-binary.ll @@ -128,15 +128,13 @@ ; X86-LABEL: freeze_add_nsw: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: incl %eax -; X86-NEXT: incl %eax +; X86-NEXT: addl $2, %eax ; X86-NEXT: retl ; ; X64-LABEL: freeze_add_nsw: ; X64: # %bb.0: ; X64-NEXT: # kill: def $edi killed $edi def $rdi -; X64-NEXT: leal 1(%rdi), %eax -; X64-NEXT: incl %eax +; X64-NEXT: leal 2(%rdi), %eax ; X64-NEXT: retq %x = add nsw i32 %a0, 1 %y = freeze i32 %x @@ -272,15 +270,15 @@ ; X86-LABEL: freeze_mul_nsw: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: leal (%eax,%eax,2), %eax ; X86-NEXT: leal (%eax,%eax,4), %eax +; X86-NEXT: leal (%eax,%eax,2), %eax ; X86-NEXT: retl ; ; X64-LABEL: freeze_mul_nsw: ; X64: # %bb.0: ; X64-NEXT: # kill: def $edi killed $edi def $rdi -; X64-NEXT: leal (%rdi,%rdi,2), %eax -; X64-NEXT: leal (%rax,%rax,4), %eax +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rax,%rax,2), %eax ; X64-NEXT: retq %x = mul nsw i32 %a0, 3 %y = freeze i32 %x @@ -344,15 +342,13 @@ ; X86-LABEL: freeze_shl_nsw: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: shll $3, %eax -; X86-NEXT: shll $5, %eax +; X86-NEXT: shll $8, %eax ; X86-NEXT: retl ; ; X64-LABEL: freeze_shl_nsw: ; X64: # %bb.0: -; X64-NEXT: # kill: def $edi killed $edi def $rdi -; X64-NEXT: leal (,%rdi,8), %eax -; X64-NEXT: shll $5, %eax +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shll $8, %eax ; X64-NEXT: retq %x = shl nsw i32 %a0, 3 %y = freeze i32 %x @@ -398,8 +394,7 @@ define <2 x i64> @freeze_shl_vec_outofrange(<2 x i64> %a0) nounwind { ; X86-LABEL: freeze_shl_vec_outofrange: ; X86: # %bb.0: -; X86-NEXT: paddq %xmm0, %xmm0 -; X86-NEXT: psllq $2, %xmm0 +; X86-NEXT: psllq $3, %xmm0 ; X86-NEXT: retl ; ; X64-LABEL: freeze_shl_vec_outofrange: