aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp19
-rw-r--r--llvm/test/CodeGen/X86/freeze-binary.ll7
2 files changed, 11 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 390ee7e..c62de47 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -14261,8 +14261,7 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
if (DAG.isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly*/ false,
/*Depth*/ 1))
continue;
- if ((!MaybePoisonOperand && N0->isOnlyUserOf(Op.getNode())) ||
- MaybePoisonOperand == Op) {
+ if (!MaybePoisonOperand || MaybePoisonOperand == Op) {
MaybePoisonOperand = Op;
continue;
}
@@ -14271,15 +14270,17 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
break;
}
if (MaybePoisonOperand) {
- // Recreate the node with the frozen maybe-poison operand.
- // TODO: Drop the isOnlyUserOf constraint and replace all users of
- // MaybePoisonOperand with FrozenMaybePoisonOperand
- // to match pushFreezeToPreventPoisonFromPropagating behavior.
+ // First, freeze the offending operand.
SDValue FrozenMaybePoisonOperand = DAG.getFreeze(MaybePoisonOperand);
+ // Then, change all other uses of unfrozen operand to use frozen operand.
+ DAG.ReplaceAllUsesOfValueWith(MaybePoisonOperand,
+ FrozenMaybePoisonOperand);
+ // But, that also updated the use in the freeze we just created, thus
+ // creating a cycle in a DAG. Let's undo that by mutating the freeze.
+ DAG.UpdateNodeOperands(FrozenMaybePoisonOperand.getNode(),
+ MaybePoisonOperand);
+ // Finally, recreate the node with the frozen maybe-poison operand.
SmallVector<SDValue> Ops(N0->op_begin(), N0->op_end());
- for (SDValue &Op : Ops)
- if (Op == MaybePoisonOperand)
- Op = FrozenMaybePoisonOperand;
// TODO: Just strip poison generating flags?
SDValue R = DAG.getNode(N0.getOpcode(), SDLoc(N0), N0->getVTList(), Ops);
assert(DAG.isGuaranteedNotToBeUndefOrPoison(R, /*PoisonOnly*/ false) &&
diff --git a/llvm/test/CodeGen/X86/freeze-binary.ll b/llvm/test/CodeGen/X86/freeze-binary.ll
index 0f3e2fb..339f1f9 100644
--- a/llvm/test/CodeGen/X86/freeze-binary.ll
+++ b/llvm/test/CodeGen/X86/freeze-binary.ll
@@ -26,7 +26,6 @@ define i32 @freeze_and_extra_use(i32 %a0, ptr %escape) nounwind {
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl %eax, (%ecx)
-; X86-NEXT: andl $15, %eax
; X86-NEXT: andl $7, %eax
; X86-NEXT: retl
;
@@ -34,7 +33,6 @@ define i32 @freeze_and_extra_use(i32 %a0, ptr %escape) nounwind {
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: movl %edi, (%rsi)
-; X64-NEXT: andl $15, %eax
; X64-NEXT: andl $7, %eax
; X64-NEXT: retq
store i32 %a0, ptr %escape
@@ -46,17 +44,14 @@ define i32 @freeze_and_extra_use(i32 %a0, ptr %escape) nounwind {
define i32 @freeze_and_extra_use2(i32 %a0, ptr %escape) nounwind {
; X86-LABEL: freeze_and_extra_use2:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: movl %ecx, %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: andl $15, %eax
-; X86-NEXT: andl %ecx, %eax
; X86-NEXT: retl
;
; X64-LABEL: freeze_and_extra_use2:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: andl $15, %eax
-; X64-NEXT: andl %edi, %eax
; X64-NEXT: retq
%x = and i32 %a0, 15
%y = freeze i32 %x