This patch adds handling for SETNE patterns with i64 inputs.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
SDValue Xor = IsRHSZero ? LHS :
SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
SDValue AC =
SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue, Xor, getI32Imm(~0U, dl)), 0); return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, AC, Xor, AC.getValue(1)), 0);
Suppose we have RHS literal 0, LHS is a var, its runtime value is also 0, the expected value of the expression should be 0. But the runtime values are:
Xor = LHS = 0 AC = Xor + ~0 = ~0, no carry result = Xor - AC - carry = 0 - (~0) = 1
So the code sequence computes out wrong result.
That's actually not what the SUBFE instruction does. As per the ISA:
subfe RT,RA,RB computes RT = ~(RA) + (RB) + CA
So in your example, it will be:
~AC + XOR + CARRY ~(~0) + 0 + 0
Which of course will just be a zero.
Then the document is wrong.
Mathematically, subtraction is
RB - RA = RB + ~RA + 1
just like the description in instruction subf.
A subtraction when considering borrowing from lower bit is
RB - RA - CA = RB + ~RA + 1 - CA = RB + ~RA + !CA
I wrote a small program to test it, you are right, the instruction subfe does
RT = ~(RA) + (RB) + CA
so
RT = (RB) + ~(RA) + CA = (RB) + ~(RA) + 1 - 1 + CA = RB - RA + CA - 1
I can't understand the mathematical meaning of the right side. And how can it be used to implement high precision integer substraction.
I understand it now.
It is because the CA flag is different than CF flag on x86 when set by SUB instruction.
On x86, CF flag means there is borrowing from highest bit when doing subtraction
On ppc, CA flag means carry flag of following addition
B - A = B + ~A + 1
so CF = !CA
so B - A - Borrow = B + ~A + 1 - CF = B + ~A + 1 - !CA = B + ~A + 1 - (1 - CA) = B + ~A + CA