As was discussed on D32916, the carry is a boolean that will respect TargetLowering::BooleanContent so we can't just accept any extension - it has to match the bool type.
I have a patch making this better. However, it has to be noted that this code is very unrepresentative from code in the field, as it essentially does a + b + carry(a, b) . This is fine to test this as it exercise edge cases, but if the tradeof is between that specific sample vs any actual sample code extracted from existing software (which I'm doing with this lagre int optimization serie) I'd rather go for the one that is actually used.
Just looking at that transform formula, it's not clear to me why it makes sense. We're turning a simple op into a more complicated op and creating a new constant operand.
Is it because there will always be a trunc/extend/mask op sitting between the carry and the add? Should we check or assert that?
In the first test case, we're going to eventually fold the addcarry with 0 operand with a uaddo. Would it make sense to have that fold directly?
I don't have a sense of how these folds work together, so if we do need this more general fold, we should have a comment to explain why it is generally good.
In this case, we're taking a boolean carry value and using it as an operand for a new ADDCARRY node that has the same boolean content requirement, so I think this part is ok.
Given that it's not clear from reading the code, please add a comment to explain the logic.
cc'ing @efriedma in case he sees a hole in that reasoning.
In practice this is better. When taking the carry as an argument, it is necessary to materialize it, which takes a register and an instruction to copy the carry from the flag register to a general purpose register. On the other hand, when passing the carry down as carry, there are usually some predicated instruction that can be used.
In addition, there are various combine you can do on top of that form, for instance if X is (add A, B) you end up with (addcarry A, B, Carry) which is preferable.
It has to match the bool type and this one is correct. But if the bool type isn't 1/0 the end result is different. We need to avoid matching SEXT and ANY_EXT here and validate that the flag is of the form 0/1 ot that a (and X, 1) is present along the way.