This is an archive of the discontinued LLVM Phabricator instance.

Fix optimisations of SELECT_CC which assumed result is boolean
ClosedPublic

Authored by olista01 on Nov 13 2014, 7:01 AM.

Details

Summary

Some optimisations in DAGCombiner cause miscompilations for targets that use TargetLowering::UndefinedBooleanContent, because they assume that the results of a SELECT_CC node are boolean values, and can be safely ANDed, ORed and XORed. These optimisations are only valid for targets that use ZeroOrOneBooleanContent or ZeroOrNegativeOneBooleanContent.

This is a follow-up to D6210/r221693.

Diff Detail

Event Timeline

olista01 updated this revision to Diff 16157.Nov 13 2014, 7:01 AM
olista01 retitled this revision from to Fix optimisations of SELECT_CC which assumed result is boolean.
olista01 updated this object.
olista01 edited the test plan for this revision. (Show Details)
olista01 added reviewers: jroelofs, arsenm.
olista01 added a subscriber: Unknown Object (MLST).

Hi Oliver,

Oh, nasty. Unfortunately I can't think of a way around the isSetCCEquivalent change. All the uses really do seem to break down. I don't think the !(setcc a, b) change is quite right though:

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
3833

I think this should use isConstTrueVal instead of hard-coding either 1 or AllOnes.

arsenm added inline comments.Nov 13 2014, 2:03 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
3833

Agree

olista01 updated this revision to Diff 16204.Nov 14 2014, 5:26 AM

Use isConstTrueVal instead of hard-coding either 1 or AllOnes.

Hi Oliver,

Thanks for updating the patch. Nearly there, I think, but there's one improvement we can make:

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
3833

isConstTrueVal is actually a bit more general than this (or it would be if it didn't have a bug itself), handling BUILD_VECTOR as well as ConstantSDNode. So you can probably drop the N1C check and use N1 directly.

E.g.

define <2 x i64> @foo(<2 x i64> %lhs, <2 x i64> %rhs) {
  %tst = icmp eq <2 x i64> %lhs, %rhs
  %ntst = xor <2 x i1> %tst, <i1 1 , i1 undef>
  %btst = sext <2 x i1> %ntst to <2 x i64>
  ret <2 x i64> %btst
}

(The undef should be a 1, I think, but that bug in isConstTrueVal (& isConstFalseVal) means the optimisation triggers with undef instead).

olista01 updated this revision to Diff 16217.Nov 14 2014, 8:55 AM

Check N1 rather than N1C, so that this optimisation also works on vectors.

t.p.northover accepted this revision.Nov 14 2014, 9:30 AM
t.p.northover added a reviewer: t.p.northover.

Thanks Oliver, this looks fine.

Tim.

This revision is now accepted and ready to land.Nov 14 2014, 9:30 AM
arsenm added inline comments.Nov 14 2014, 2:57 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
648–650

Is this really necessary? I believe isConstTrue should do the correct thing for for UndefinedBooleanContent

t.p.northover added inline comments.Nov 14 2014, 3:22 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
648–650

The problem is that most (all?) contexts this function is used in, the output isn't necessarily a boolean. E.g.

(and (select_cc L1, R1, 0x1230, 0x4561), (select_cc L2, R2, 0x7890, 0xabc1))

That's going to be a very specific constant, but any argument based on thinking of it as equivalent to

(and (setcc L1, R1), (setcc L2, R2))

is going to be on very shaky ground. Thinking about it, you could probably allow it if the type is still i1 or <N x i1>, but not more generally.

olista01 closed this revision.Nov 17 2014, 2:49 AM

Thanks, committed revision 222123.