================
@@ -12592,93 +12596,57 @@ SDValue DAGCombiner::visitConstantTimeSelect(SDNode
*N) {
SDLoc DL(N);
SDNodeFlags Flags = N->getFlags();
- if (SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(N, DL, DAG))
- return V;
-
// ctselect (not Cond), N1, N2 -> ctselect Cond, N2, N1
+ // This is a CT-safe canonicalization: flip negated condition by swapping
+ // arms. extractBooleanFlip only matches boolean xor-with-1, so this
preserves
+ // dataflow semantics and does not introduce data-dependent control flow.
if (SDValue F = extractBooleanFlip(N0, DAG, TLI, false)) {
SDValue SelectOp = DAG.getNode(ISD::CTSELECT, DL, VT, F, N2, N1);
SelectOp->setFlags(Flags);
return SelectOp;
}
if (VT0 == MVT::i1) {
- // The code in this block deals with the following 2 equivalences:
- // select(C0|C1, x, y) <=> select(C0, x, select(C1, x, y))
- // select(C0&C1, x, y) <=> select(C0, select(C1, x, y), y)
- // The target can specify its preferred form with the
- // shouldNormalizeToSelectSequence() callback. However we always transform
- // to the right anyway if we find the inner select exists in the DAG anyway
- // and we always transform to the left side if we know that we can further
- // optimize the combination of the conditions.
- bool normalizeToSequence =
- TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT);
- // ctselect (and Cond0, Cond1), X, Y
- // -> ctselect Cond0, (ctselect Cond1, X, Y), Y
- if (N0->getOpcode() == ISD::AND && N0->hasOneUse()) {
- SDValue Cond0 = N0->getOperand(0);
- SDValue Cond1 = N0->getOperand(1);
- SDValue InnerSelect = DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(),
- Cond1, N1, N2, Flags);
- if (normalizeToSequence || !InnerSelect.use_empty())
- return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Cond0,
- InnerSelect, N2, Flags);
- // Cleanup on failure.
- if (InnerSelect.use_empty())
- recursivelyDeleteUnusedNodes(InnerSelect.getNode());
- }
- // ctselect (or Cond0, Cond1), X, Y -> ctselect Cond0, X, (ctselect Cond1,
- // X, Y)
- if (N0->getOpcode() == ISD::OR && N0->hasOneUse()) {
- SDValue Cond0 = N0->getOperand(0);
- SDValue Cond1 = N0->getOperand(1);
- SDValue InnerSelect = DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(),
- Cond1, N1, N2, Flags);
- if (normalizeToSequence || !InnerSelect.use_empty())
- return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Cond0, N1,
- InnerSelect, Flags);
- // Cleanup on failure.
- if (InnerSelect.use_empty())
- recursivelyDeleteUnusedNodes(InnerSelect.getNode());
- }
-
- // ctselect Cond0, (ctselect Cond1, X, Y), Y -> ctselect (and Cond0,
Cond1),
- // X, Y
+ // Nested CTSELECT merging optimizations for i1 conditions.
+ // These are CT-safe because:
+ // 1. AND/OR are bitwise operations that execute in constant time
+ // 2. The optimization combines two sequential CTSELECTs into one,
+ // reducing
+ // the total number of constant-time operations without changing
+ // semantics
----------------
wizardengineer wrote:
nit: The formatting for this seems a bit off. Would it be okay if we can fix
this?
https://github.com/llvm/llvm-project/pull/180883
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits