@@ -16918,6 +16918,8 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
1691816918 // creating a cycle in a DAG. Let's undo that by mutating the freeze.
1691916919 assert(N->getOperand(0) == FrozenN0 && "Expected cycle in DAG");
1692016920 DAG.UpdateNodeOperands(N, N0);
16921+ // Revisit the node.
16922+ AddToWorklist(N);
1692116923 return FrozenN0;
1692216924 }
1692316925
@@ -16972,72 +16974,81 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
1697216974 }
1697316975 }
1697416976
16975- SmallSet<SDValue, 8> MaybePoisonOperands;
16976- SmallVector<unsigned, 8> MaybePoisonOperandNumbers;
16977- for (auto [OpNo, Op] : enumerate(N0->ops())) {
16978- if (DAG.isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly=*/false))
16979- continue;
16980- bool HadMaybePoisonOperands = !MaybePoisonOperands.empty();
16981- bool IsNewMaybePoisonOperand = MaybePoisonOperands.insert(Op).second;
16982- if (IsNewMaybePoisonOperand)
16983- MaybePoisonOperandNumbers.push_back(OpNo);
16984- if (!HadMaybePoisonOperands)
16985- continue;
16986- if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
16987- // Multiple maybe-poison ops when not allowed - bail out.
16988- return SDValue();
16977+ SmallVector<SDValue> Ops;
16978+ if (AllowMultipleMaybePoisonOperands) {
16979+ // Collect and freeze all operands.
16980+ Ops = SmallVector<SDValue>(N0->ops());
16981+ for (SDValue &Op : Ops)
16982+ Op = DAG.getFreeze(Op);
16983+ } else {
16984+ SmallSet<SDValue, 8> MaybePoisonOperands;
16985+ SmallVector<unsigned, 8> MaybePoisonOperandNumbers;
16986+ for (auto [OpNo, Op] : enumerate(N0->ops())) {
16987+ if (DAG.isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly=*/false))
16988+ continue;
16989+ bool HadMaybePoisonOperands = !MaybePoisonOperands.empty();
16990+ bool IsNewMaybePoisonOperand = MaybePoisonOperands.insert(Op).second;
16991+ if (IsNewMaybePoisonOperand)
16992+ MaybePoisonOperandNumbers.push_back(OpNo);
16993+ if (!HadMaybePoisonOperands)
16994+ continue;
16995+ if (IsNewMaybePoisonOperand) {
16996+ // Multiple maybe-poison ops when not allowed - bail out.
16997+ return SDValue();
16998+ }
16999+ }
17000+ // NOTE: the whole op may be not guaranteed to not be undef or poison
17001+ // because it could create undef or poison due to it's poison-generating
17002+ // flags. So not finding any maybe-poison operands is fine.
17003+
17004+ for (unsigned OpNo : MaybePoisonOperandNumbers) {
17005+ // N0 can mutate during iteration, so make sure to refetch the maybe
17006+ // poison operands via the operand numbers. The typical scenario is that
17007+ // we have something like this
17008+ // t262: i32 = freeze t181
17009+ // t150: i32 = ctlz_zero_undef t262
17010+ // t184: i32 = ctlz_zero_undef t181
17011+ // t268: i32 = select_cc t181, Constant:i32<0>, t184, t186, setne:ch
17012+ // When freezing the t181 operand we get t262 back, and then the
17013+ // ReplaceAllUsesOfValueWith call will not only replace t181 by t262, but
17014+ // also recursively replace t184 by t150.
17015+ SDValue MaybePoisonOperand = N->getOperand(0).getOperand(OpNo);
17016+ // Don't replace every single UNDEF everywhere with frozen UNDEF, though.
17017+ if (MaybePoisonOperand.isUndef())
17018+ continue;
17019+ // First, freeze each offending operand.
17020+ SDValue FrozenMaybePoisonOperand = DAG.getFreeze(MaybePoisonOperand);
17021+ // Then, change all other uses of unfrozen operand to use frozen operand.
17022+ DAG.ReplaceAllUsesOfValueWith(MaybePoisonOperand,
17023+ FrozenMaybePoisonOperand);
17024+ if (FrozenMaybePoisonOperand.getOpcode() == ISD::FREEZE &&
17025+ FrozenMaybePoisonOperand.getOperand(0) == FrozenMaybePoisonOperand) {
17026+ // But, that also updated the use in the freeze we just created, thus
17027+ // creating a cycle in a DAG. Let's undo that by mutating the freeze.
17028+ DAG.UpdateNodeOperands(FrozenMaybePoisonOperand.getNode(),
17029+ MaybePoisonOperand);
17030+ }
17031+
17032+ // This node has been merged with another.
17033+ if (N->getOpcode() == ISD::DELETED_NODE)
17034+ return SDValue(N, 0);
1698917035 }
16990- }
16991- // NOTE: the whole op may be not guaranteed to not be undef or poison because
16992- // it could create undef or poison due to it's poison-generating flags.
16993- // So not finding any maybe-poison operands is fine.
16994-
16995- for (unsigned OpNo : MaybePoisonOperandNumbers) {
16996- // N0 can mutate during iteration, so make sure to refetch the maybe poison
16997- // operands via the operand numbers. The typical scenario is that we have
16998- // something like this
16999- // t262: i32 = freeze t181
17000- // t150: i32 = ctlz_zero_undef t262
17001- // t184: i32 = ctlz_zero_undef t181
17002- // t268: i32 = select_cc t181, Constant:i32<0>, t184, t186, setne:ch
17003- // When freezing the t181 operand we get t262 back, and then the
17004- // ReplaceAllUsesOfValueWith call will not only replace t181 by t262, but
17005- // also recursively replace t184 by t150.
17006- SDValue MaybePoisonOperand = N->getOperand(0).getOperand(OpNo);
17007- // Don't replace every single UNDEF everywhere with frozen UNDEF, though.
17008- if (MaybePoisonOperand.isUndef())
17009- continue;
17010- // First, freeze each offending operand.
17011- SDValue FrozenMaybePoisonOperand = DAG.getFreeze(MaybePoisonOperand);
17012- // Then, change all other uses of unfrozen operand to use frozen operand.
17013- DAG.ReplaceAllUsesOfValueWith(MaybePoisonOperand, FrozenMaybePoisonOperand);
17014- if (FrozenMaybePoisonOperand.getOpcode() == ISD::FREEZE &&
17015- FrozenMaybePoisonOperand.getOperand(0) == FrozenMaybePoisonOperand) {
17016- // But, that also updated the use in the freeze we just created, thus
17017- // creating a cycle in a DAG. Let's undo that by mutating the freeze.
17018- DAG.UpdateNodeOperands(FrozenMaybePoisonOperand.getNode(),
17019- MaybePoisonOperand);
17020- }
17021-
17022- // This node has been merged with another.
17023- if (N->getOpcode() == ISD::DELETED_NODE)
17024- return SDValue(N, 0);
17025- }
1702617036
17027- assert(N->getOpcode() != ISD::DELETED_NODE && "Node was deleted!");
17037+ assert(N->getOpcode() != ISD::DELETED_NODE && "Node was deleted!");
1702817038
17029- // The whole node may have been updated, so the value we were holding
17030- // may no longer be valid. Re-fetch the operand we're `freeze`ing.
17031- N0 = N->getOperand(0);
17039+ // The whole node may have been updated, so the value we were holding
17040+ // may no longer be valid. Re-fetch the operand we're `freeze`ing.
17041+ N0 = N->getOperand(0);
1703217042
17033- // Finally, recreate the node, it's operands were updated to use
17034- // frozen operands, so we just need to use it's "original" operands.
17035- SmallVector<SDValue> Ops(N0->ops());
17036- // TODO: ISD::UNDEF and ISD::POISON should get separate handling, but best
17037- // leave for a future patch.
17038- for (SDValue &Op : Ops) {
17039- if (Op.isUndef())
17040- Op = DAG.getFreeze(Op);
17043+ // Finally, recreate the node, it's operands were updated to use
17044+ // frozen operands, so we just need to use it's "original" operands.
17045+ Ops = SmallVector<SDValue>(N0->ops());
17046+ // TODO: ISD::UNDEF and ISD::POISON should get separate handling, but best
17047+ // leave for a future patch.
17048+ for (SDValue &Op : Ops) {
17049+ if (Op.isUndef())
17050+ Op = DAG.getFreeze(Op);
17051+ }
1704117052 }
1704217053
1704317054 SDLoc DL(N0);
0 commit comments