diff options
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 36 | 
1 files changed, 32 insertions, 4 deletions
| diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 02bf97cacb8..5d5caa2e9a7 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -807,10 +807,38 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,    }    case X86::BI__builtin_ia32_palignr128:    case X86::BI__builtin_ia32_palignr: { -    Function *F = CGM.getIntrinsic(BuiltinID == X86::BI__builtin_ia32_palignr128 ? -				   Intrinsic::x86_ssse3_palign_r_128 : -				   Intrinsic::x86_ssse3_palign_r); -    return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size()); +    unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); +     +    // If palignr is shifting the pair of input vectors less than 17 bytes, +    // emit a shuffle instruction. +    if (shiftVal <= 16) { +      const llvm::Type *IntTy = llvm::Type::getInt32Ty(VMContext); + +      llvm::SmallVector<llvm::Constant*, 16> Indices; +      for (unsigned i = 0; i != 16; ++i) +        Indices.push_back(llvm::ConstantInt::get(IntTy, shiftVal + i)); +       +      Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size()); +      return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); +    } +     +    // If palignr is shifting the pair of input vectors more than 16 but less +    // than 32 bytes, emit a logical right shift of the destination. +    if (shiftVal < 32) { +      const llvm::Type *EltTy = llvm::Type::getInt64Ty(VMContext); +      const llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2); +      const llvm::Type *IntTy = llvm::Type::getInt32Ty(VMContext); +       +      Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); +      Ops[1] = llvm::ConstantInt::get(IntTy, (shiftVal-16) * 8); +       +      // create i32 constant +      llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_psrl_dq); +      return Builder.CreateCall(F, &Ops[0], &Ops[0] + 2, "palignr"); +    } +     +    // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. +    return llvm::Constant::getNullValue(ConvertType(E->getType()));    }    }  } | 

