This is an archive of the discontinued LLVM Phabricator instance.

[PowerPC] Eliminate compares - add i64 sext/zext handling for SETNE
ClosedPublic

Authored by nemanjai on May 31 2017, 5:32 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

nemanjai created this revision.May 31 2017, 5:32 AM
echristo accepted this revision.Jun 5 2017, 1:01 PM

Feel free to commit any patches that look like this to this area :)

This revision is now accepted and ready to land.Jun 5 2017, 1:01 PM
This revision was automatically updated to reflect the committed changes.
Carrot added a subscriber: Carrot.Jun 22 2017, 4:29 PM

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.

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.

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

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.

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