forked from OSchip/llvm-project
[DAG] visitFREEZE - generalize freeze(op()) -> op(freeze()) to any number of operands
canCreateUndefOrPoison currently only handles unary ops, but we intend to change that soon - this more closely matches the pushFreezeToPreventPoisonFromPropagating behaviour where the freeze is pushed up to a single operand value, as long as all others are guaranteed not to be poison/undef. However, pushFreezeToPreventPoisonFromPropagating would freeze all uses of the value - whilst this variant requires the frozen value to be only used in the op - we can look at generalize multiple uses later if the need arises.
This commit is contained in:
parent
1f02ad7131
commit
8623da5f74
|
@ -13868,13 +13868,40 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
|
||||||
if (DAG.isGuaranteedNotToBeUndefOrPoison(N0, /*PoisonOnly*/ false))
|
if (DAG.isGuaranteedNotToBeUndefOrPoison(N0, /*PoisonOnly*/ false))
|
||||||
return N0;
|
return N0;
|
||||||
|
|
||||||
// Fold freeze(unaryop(x)) -> unaryop(freeze(x)).
|
// Fold freeze(op(x,y,z)) -> op(freeze(x),y,z).
|
||||||
// TODO: Replace with pushFreezeToPreventPoisonFromPropagating fold and
|
// Try to push freeze through instructions that propagate but don't produce
|
||||||
// support getNumOperands() >= 1.
|
// poison as far as possible. If an operand of freeze follows three
|
||||||
if (N0.getNumOperands() == 1 &&
|
// conditions 1) one-use, 2) does not produce poison, and 3) has all but one
|
||||||
!DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false) && N0->hasOneUse())
|
// guaranteed-non-poison operands then push the freeze through to the one
|
||||||
return DAG.getNode(N0.getOpcode(), SDLoc(N0), N->getValueType(0),
|
// operand that is not guaranteed non-poison.
|
||||||
DAG.getFreeze(N0.getOperand(0)));
|
if (!DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false) &&
|
||||||
|
N0->getNumValues() == 1 && N0->hasOneUse()) {
|
||||||
|
SDValue MaybePoisonOperand;
|
||||||
|
for (SDValue Op : N0->ops()) {
|
||||||
|
if (DAG.isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly*/ false))
|
||||||
|
continue;
|
||||||
|
if ((!MaybePoisonOperand && N0->isOnlyUserOf(Op.getNode())) ||
|
||||||
|
MaybePoisonOperand == Op) {
|
||||||
|
MaybePoisonOperand = Op;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Multiple maybe-poison ops - bail out.
|
||||||
|
MaybePoisonOperand = SDValue();
|
||||||
|
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.
|
||||||
|
SDValue FrozenMaybePoisonOperand = DAG.getFreeze(MaybePoisonOperand);
|
||||||
|
SmallVector<SDValue> Ops(N0->op_begin(), N0->op_end());
|
||||||
|
for (SDValue &Op : Ops)
|
||||||
|
if (Op == MaybePoisonOperand)
|
||||||
|
Op = FrozenMaybePoisonOperand;
|
||||||
|
return DAG.getNode(N0.getOpcode(), SDLoc(N0), N0->getVTList(), Ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue