Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong select folding for undef conditions by InstCombine #98435

Closed
bongjunj opened this issue Jul 11, 2024 · 4 comments · Fixed by #102244
Closed

Wrong select folding for undef conditions by InstCombine #98435

bongjunj opened this issue Jul 11, 2024 · 4 comments · Fixed by #102244

Comments

@bongjunj
Copy link

if (Value *S = simplifyWithOpReplaced(FalseVal, CondVal,
ConstantInt::getFalse(CondType), SQ,
/* AllowRefinement */ true))
return replaceOperand(SI, 2, S);

Alive2 report: https://alive2.llvm.org/ce/z/Qtu72J

----------------------------------------
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  %val2 = select <2 x i1> %val0, <2 x i1> %val0, <2 x i1> %val0
  %val3 = select <2 x i1> { undef, 1 }, <2 x i1> { 1, 1 }, <2 x i1> %val2
  ret <2 x i1> %val3
}
=>
define <2 x i1> @fun0(<2 x i1> %val0, <2 x i1> %val1) {
#0:
  ret <2 x i1> { poison, 1 }
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<2 x i1> %val0 = < #x0 (0), #x0 (0) >
<2 x i1> %val1 = < #x0 (0), #x0 (0) >

Source:
<2 x i1> %val2 = < #x0 (0), #x0 (0) >
<2 x i1> %val3 = < #x0 (0)	[based on undef value], #x1 (1) >

Target:
Source value: < #x0 (0), #x1 (1) >
Target value: < poison, #x1 (1) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
@jf-botto
Copy link
Contributor

jf-botto commented Aug 6, 2024

Would this issue be to fix InstCombine to not try to optimise it or get InstCombine to pick <2 x i1> { 1, 1 } because undef let's it pick either values and picking a constant vector is better than picking a variable?

@nikic
Copy link
Contributor

nikic commented Aug 6, 2024

The problematic step seems to be this one: https://alive2.llvm.org/ce/z/C2waWU

I don't think the quoted code is responsible for this, as it is guarded by !isa<Constant>(CondVal).

@jf-botto
Copy link
Contributor

jf-botto commented Aug 6, 2024

I think the problem is with how SimplifyDemandedVectorElts handles the undef:

case Instruction::Select: {
// If this is a vector select, try to transform the select condition based
// on the current demanded elements.
SelectInst *Sel = cast<SelectInst>(I);
if (Sel->getCondition()->getType()->isVectorTy()) {
// TODO: We are not doing anything with PoisonElts based on this call.
// It is overwritten below based on the other select operands. If an
// element of the select condition is known undef, then we are free to
// choose the output value from either arm of the select. If we know that
// one of those values is undef, then the output can be undef.
simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
}
// Next, see if we can transform the arms of the select.
APInt DemandedLHS(DemandedElts), DemandedRHS(DemandedElts);
if (auto *CV = dyn_cast<ConstantVector>(Sel->getCondition())) {
for (unsigned i = 0; i < VWidth; i++) {
// isNullValue() always returns false when called on a ConstantExpr.
// Skip constant expressions to avoid propagating incorrect information.
Constant *CElt = CV->getAggregateElement(i);
if (isa<ConstantExpr>(CElt))
continue;
// TODO: If a select condition element is undef, we can demand from
// either side. If one side is known undef, choosing that side would
// propagate undef.
if (CElt->isNullValue())
DemandedLHS.clearBit(i);
else
DemandedRHS.clearBit(i);
}
}
simplifyAndSetOp(I, 1, DemandedLHS, PoisonElts2);
simplifyAndSetOp(I, 2, DemandedRHS, PoisonElts3);
// Output elements are undefined if the element from each arm is undefined.
// TODO: This can be improved. See comment in select condition handling.
PoisonElts = PoisonElts2 & PoisonElts3;
break;
}

@nikic
Copy link
Contributor

nikic commented Aug 6, 2024

@jf-botto Agree. It assumes that !isNullValue() means "is true", which is not the case.

@nikic nikic closed this as completed in 9304af3 Aug 9, 2024
bwendling pushed a commit to bwendling/llvm-project that referenced this issue Aug 15, 2024
…nts (llvm#102244)

This PR fixes llvm#98435.
`SimplifyDemandedVectorElts` mishandles the undef by assuming that
!isNullValue() means the condition is true.

By preventing any value that we're not certain equals 1 or 0, it avoids
having to make any particular choice by not demanding bits from a
particular branch with potentially picking a wrong value.

Proof: https://alive2.llvm.org/ce/z/r8CmEu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants