Fix ExpandShiftWithUnknownAmountBit, which was completely bogus.

Pointed out by Javier Martinez (who also provided a patch).  Since
this logic is not used on (for example) x86, I guess nobody noticed.
Tested by generating SHL, SRL, SRA on various choices of i64 for all
possible shift amounts, and comparing with gcc.  Since I did this on
x86-32, I had to force the use of ExpandShiftWithUnknownAmountBit.
What I'm saying here is that I don't have a testcase I can add to the
repository.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90482 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2009-12-03 21:37:32 +00:00
parent f4811a9694
commit 9993b88f06

View File

@ -1167,55 +1167,56 @@ ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) {
GetExpandedInteger(N->getOperand(0), InL, InH); GetExpandedInteger(N->getOperand(0), InL, InH);
SDValue NVBitsNode = DAG.getConstant(NVTBits, ShTy); SDValue NVBitsNode = DAG.getConstant(NVTBits, ShTy);
SDValue Amt2 = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt); SDValue AmtExcess = DAG.getNode(ISD::SUB, dl, ShTy, Amt, NVBitsNode);
SDValue Cmp = DAG.getSetCC(dl, TLI.getSetCCResultType(ShTy), SDValue AmtLack = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt);
Amt, NVBitsNode, ISD::SETULT); SDValue isShort = DAG.getSetCC(dl, TLI.getSetCCResultType(ShTy),
Amt, NVBitsNode, ISD::SETULT);
SDValue Lo1, Hi1, Lo2, Hi2; SDValue LoS, HiS, LoL, HiL;
switch (N->getOpcode()) { switch (N->getOpcode()) {
default: llvm_unreachable("Unknown shift"); default: llvm_unreachable("Unknown shift");
case ISD::SHL: case ISD::SHL:
// ShAmt < NVTBits // Short: ShAmt < NVTBits
Lo1 = DAG.getConstant(0, NVT); // Low part is zero. LoS = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt);
Hi1 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); // High part from Lo part. HiS = DAG.getNode(ISD::OR, dl, NVT,
// ShAmt >= NVTBits
Lo2 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt);
Hi2 = DAG.getNode(ISD::OR, dl, NVT,
DAG.getNode(ISD::SHL, dl, NVT, InH, Amt), DAG.getNode(ISD::SHL, dl, NVT, InH, Amt),
DAG.getNode(ISD::SRL, dl, NVT, InL, Amt2)); DAG.getNode(ISD::SRL, dl, NVT, InL, AmtLack));
Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); // Long: ShAmt >= NVTBits
Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); LoL = DAG.getConstant(0, NVT); // Lo part is zero.
HiL = DAG.getNode(ISD::SHL, dl, NVT, InL, AmtExcess); // Hi from Lo part.
Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL);
Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL);
return true; return true;
case ISD::SRL: case ISD::SRL:
// ShAmt < NVTBits // Short: ShAmt < NVTBits
Hi1 = DAG.getConstant(0, NVT); // Hi part is zero. HiS = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt);
Lo1 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); // Lo part from Hi part. LoS = DAG.getNode(ISD::OR, dl, NVT,
DAG.getNode(ISD::SRL, dl, NVT, InL, Amt),
DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack));
// ShAmt >= NVTBits // Long: ShAmt >= NVTBits
Hi2 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); HiL = DAG.getConstant(0, NVT); // Hi part is zero.
Lo2 = DAG.getNode(ISD::OR, dl, NVT, LoL = DAG.getNode(ISD::SRL, dl, NVT, InH, AmtExcess); // Lo from Hi part.
DAG.getNode(ISD::SRL, dl, NVT, InL, Amt),
DAG.getNode(ISD::SHL, dl, NVT, InH, Amt2));
Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL);
Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL);
return true; return true;
case ISD::SRA: case ISD::SRA:
// ShAmt < NVTBits // Short: ShAmt < NVTBits
Hi1 = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign extend high part. HiS = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt);
DAG.getConstant(NVTBits-1, ShTy)); LoS = DAG.getNode(ISD::OR, dl, NVT,
Lo1 = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); // Lo part from Hi part.
// ShAmt >= NVTBits
Hi2 = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt);
Lo2 = DAG.getNode(ISD::OR, dl, NVT,
DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), DAG.getNode(ISD::SRL, dl, NVT, InL, Amt),
DAG.getNode(ISD::SHL, dl, NVT, InH, Amt2)); DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack));
Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); // Long: ShAmt >= NVTBits
Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); HiL = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign of Hi part.
DAG.getConstant(NVTBits-1, ShTy));
LoL = DAG.getNode(ISD::SRA, dl, NVT, InH, AmtExcess); // Lo from Hi part.
Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL);
Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL);
return true; return true;
} }