diff options
author | Duncan Sands <baldrick@free.fr> | 2009-12-03 21:37:32 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2009-12-03 21:37:32 +0000 |
commit | 9993b88f06fd54c0be31d35f0970ada70a4c0439 (patch) | |
tree | b49e3cf54a01ad529102922891d25639949f0273 /lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | |
parent | f4811a96941433fc3828869d76dfeba5ec5decd3 (diff) |
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
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 8ac8063be9..5599d25f6e 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1167,55 +1167,56 @@ ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { GetExpandedInteger(N->getOperand(0), InL, InH); SDValue NVBitsNode = DAG.getConstant(NVTBits, ShTy); - SDValue Amt2 = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt); - SDValue Cmp = DAG.getSetCC(dl, TLI.getSetCCResultType(ShTy), - Amt, NVBitsNode, ISD::SETULT); + SDValue AmtExcess = DAG.getNode(ISD::SUB, dl, ShTy, Amt, NVBitsNode); + SDValue AmtLack = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt); + 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()) { default: llvm_unreachable("Unknown shift"); case ISD::SHL: - // ShAmt < NVTBits - Lo1 = DAG.getConstant(0, NVT); // Low part is zero. - Hi1 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); // High part from Lo part. - - // ShAmt >= NVTBits - Lo2 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); - Hi2 = DAG.getNode(ISD::OR, dl, NVT, + // Short: ShAmt < NVTBits + LoS = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); + HiS = DAG.getNode(ISD::OR, dl, NVT, DAG.getNode(ISD::SHL, dl, NVT, InH, Amt), - DAG.getNode(ISD::SRL, dl, NVT, InL, Amt2)); + DAG.getNode(ISD::SRL, dl, NVT, InL, AmtLack)); + + // Long: ShAmt >= NVTBits + 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, Cmp, Lo1, Lo2); - Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL); return true; case ISD::SRL: - // ShAmt < NVTBits - Hi1 = DAG.getConstant(0, NVT); // Hi part is zero. - Lo1 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); // Lo part from Hi part. - - // ShAmt >= NVTBits - Hi2 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); - Lo2 = DAG.getNode(ISD::OR, dl, NVT, - 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); - Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + // Short: ShAmt < NVTBits + HiS = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); + LoS = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), + DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack)); + + // Long: ShAmt >= NVTBits + HiL = DAG.getConstant(0, NVT); // Hi part is zero. + LoL = DAG.getNode(ISD::SRL, 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; case ISD::SRA: - // ShAmt < NVTBits - Hi1 = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign extend high part. - DAG.getConstant(NVTBits-1, ShTy)); - 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, + // Short: ShAmt < NVTBits + HiS = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); + LoS = DAG.getNode(ISD::OR, dl, NVT, DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), - DAG.getNode(ISD::SHL, dl, NVT, InH, Amt2)); + DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack)); + + // Long: ShAmt >= NVTBits + 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, Cmp, Lo1, Lo2); - Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL); return true; } |