diff options
author | Michael Liao <michael.liao@intel.com> | 2013-10-15 17:51:02 +0000 |
---|---|---|
committer | Michael Liao <michael.liao@intel.com> | 2013-10-15 17:51:02 +0000 |
commit | dc8c044a9a3e00cab52ca204717de7aee9dab1be (patch) | |
tree | 89ad409fb774f860488c22c9bf0af76e96f9d7ad | |
parent | d45b3c4653dc4b18074b04662b6d0009880214e3 (diff) | |
download | external_llvm-dc8c044a9a3e00cab52ca204717de7aee9dab1be.zip external_llvm-dc8c044a9a3e00cab52ca204717de7aee9dab1be.tar.gz external_llvm-dc8c044a9a3e00cab52ca204717de7aee9dab1be.tar.bz2 |
Fix PR16807
- Lower signed division by constant powers-of-2 to target-independent
DAG operators instead of target-dependent ones to support them better
on targets where vector types are legal but shift operators on that
types are illegal. E.g., on AVX, PSRAW is only available on <8 x i16>
though <16 x i16> is a legal type.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192721 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 22 | ||||
-rw-r--r-- | test/CodeGen/X86/pr16807.ll | 18 |
2 files changed, 34 insertions, 6 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 62966de..8e3a4d7 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -12467,14 +12467,24 @@ static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG) { (SplatValue.isPowerOf2() || (-SplatValue).isPowerOf2())) { unsigned lg2 = SplatValue.countTrailingZeros(); // Splat the sign bit. - SDValue Sz = DAG.getConstant(EltTy.getSizeInBits()-1, MVT::i32); - SDValue SGN = getTargetVShiftNode(X86ISD::VSRAI, dl, VT, N0, Sz, DAG); + SmallVector<SDValue, 16> Sz(NumElts, + DAG.getConstant(EltTy.getSizeInBits() - 1, + EltTy)); + SDValue SGN = DAG.getNode(ISD::SRA, dl, VT, N0, + DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Sz[0], + NumElts)); // Add (N0 < 0) ? abs2 - 1 : 0; - SDValue Amt = DAG.getConstant(EltTy.getSizeInBits() - lg2, MVT::i32); - SDValue SRL = getTargetVShiftNode(X86ISD::VSRLI, dl, VT, SGN, Amt, DAG); + SmallVector<SDValue, 16> Amt(NumElts, + DAG.getConstant(EltTy.getSizeInBits() - lg2, + EltTy)); + SDValue SRL = DAG.getNode(ISD::SRL, dl, VT, SGN, + DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Amt[0], + NumElts)); SDValue ADD = DAG.getNode(ISD::ADD, dl, VT, N0, SRL); - SDValue Lg2Amt = DAG.getConstant(lg2, MVT::i32); - SDValue SRA = getTargetVShiftNode(X86ISD::VSRAI, dl, VT, ADD, Lg2Amt, DAG); + SmallVector<SDValue, 16> Lg2Amt(NumElts, DAG.getConstant(lg2, EltTy)); + SDValue SRA = DAG.getNode(ISD::SRA, dl, VT, ADD, + DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Lg2Amt[0], + NumElts)); // If we're dividing by a positive value, we're done. Otherwise, we must // negate the result. diff --git a/test/CodeGen/X86/pr16807.ll b/test/CodeGen/X86/pr16807.ll new file mode 100644 index 0000000..6d55d99 --- /dev/null +++ b/test/CodeGen/X86/pr16807.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu -mcpu=core-avx-i | FileCheck %s + +define <16 x i16> @f_fu(<16 x i16> %bf) { +allocas: + %avg.i.i = sdiv <16 x i16> %bf, <i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4> + ret <16 x i16> %avg.i.i +} + +; CHECK: f_fu +; CHECK: psraw +; CHECK: psrlw +; CHECK: paddw +; CHECK: psraw +; CHECK: psraw +; CHECK: psrlw +; CHECK: paddw +; CHECK: psraw +; CHECK: ret |