Skip to content

Commit

Permalink
Implement transpose/zip/unzip & table lookup.
Browse files Browse the repository at this point in the history
Test out some basic constant-checking.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105667 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
sampo3k committed Jun 9, 2010
1 parent 9b065dd commit 1c2a88c
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 9 deletions.
2 changes: 0 additions & 2 deletions include/clang/Basic/BuiltinsARM.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ BUILTIN(__builtin_neon_vcvt_u32_v, "V2iV8ci", "n")
BUILTIN(__builtin_neon_vcvtq_u32_v, "V4iV16ci", "n")
BUILTIN(__builtin_neon_vext_v, "V8cV8cV8cii", "n")
BUILTIN(__builtin_neon_vextq_v, "V16cV16cV16cii", "n")
BUILTIN(__builtin_neon_vget_high_v, "V8cV16ci", "n")
BUILTIN(__builtin_neon_vget_lane_i8, "UcV8ci", "n")
BUILTIN(__builtin_neon_vget_lane_i16, "UsV8ci", "n")
BUILTIN(__builtin_neon_vget_lane_i32, "UiV8ci", "n")
Expand All @@ -75,7 +74,6 @@ BUILTIN(__builtin_neon_vgetq_lane_i32, "UiV16ci", "n")
BUILTIN(__builtin_neon_vgetq_lane_f32, "fV16ci", "n")
BUILTIN(__builtin_neon_vget_lane_i64, "ULLiV8ci", "n")
BUILTIN(__builtin_neon_vgetq_lane_i64, "ULLiV16ci", "n")
BUILTIN(__builtin_neon_vget_low_v, "V8cV16ci", "n")
BUILTIN(__builtin_neon_vhadd_v, "V8cV8cV8ci", "n")
BUILTIN(__builtin_neon_vhaddq_v, "V16cV16cV16ci", "n")
BUILTIN(__builtin_neon_vhsub_v, "V8cV8cV8ci", "n")
Expand Down
85 changes: 81 additions & 4 deletions lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,18 +1051,95 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vextq_v: {
ConstantInt *C = dyn_cast<ConstantInt>(Ops[2]);
int CV = C->getSExtValue();

SmallVector<Constant*, 8> Indices;

const llvm::Type *I32Ty = llvm::Type::getInt32Ty(VMContext);

SmallVector<Constant*, 16> Indices;
for (unsigned i = 0, e = cast<llvm::VectorType>(Ty)->getNumElements();
i != e; ++i)
Indices.push_back(ConstantInt::get(I32Ty, i+CV));

Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
return Builder.CreateShuffleVector(Ops[0], Ops[1], SV);
return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vext");
}
case ARM::BI__builtin_neon_vtbl1_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1),
Ops, "vtbl1");
case ARM::BI__builtin_neon_vtbl2_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl2),
Ops, "vtbl2");
case ARM::BI__builtin_neon_vtbl3_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl3),
Ops, "vtbl3");
case ARM::BI__builtin_neon_vtbl4_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl4),
Ops, "vtbl4");
case ARM::BI__builtin_neon_vtbx1_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx1),
Ops, "vtbx1");
case ARM::BI__builtin_neon_vtbx2_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx2),
Ops, "vtbx2");
case ARM::BI__builtin_neon_vtbx3_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx3),
Ops, "vtbx3");
case ARM::BI__builtin_neon_vtbx4_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx4),
Ops, "vtbx4");
case ARM::BI__builtin_neon_vtst_v:
case ARM::BI__builtin_neon_vtstq_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]);
Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0],
ConstantAggregateZero::get(Ty));
return Builder.CreateSExt(Ops[0], Ty, "vtst");
}
// FIXME: transpose/zip/unzip don't currently match patterns for
// the non-q variants, but emitting 2 shufflevectors seems like a hack.
case ARM::BI__builtin_neon_vtrn_v:
case ARM::BI__builtin_neon_vtrnq_v: {
const llvm::Type *I32Ty = llvm::Type::getInt32Ty(VMContext);
SmallVector<Constant*, 32> Indices;
unsigned nElts = cast<llvm::VectorType>(Ty)->getNumElements();
for (unsigned vi = 0; vi != 2; ++vi) {
for (unsigned i = 0; i != nElts; i += 2) {
Indices.push_back(ConstantInt::get(I32Ty, i+vi));
Indices.push_back(ConstantInt::get(I32Ty, i+nElts+vi));
}
}
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vtrn");
}
case ARM::BI__builtin_neon_vuzp_v:
case ARM::BI__builtin_neon_vuzpq_v: {
const llvm::Type *I32Ty = llvm::Type::getInt32Ty(VMContext);
SmallVector<Constant*, 32> Indices;
unsigned nElts = cast<llvm::VectorType>(Ty)->getNumElements();
for (unsigned vi = 0; vi != 2; ++vi)
for (unsigned i = 0; i != nElts; ++i)
Indices.push_back(ConstantInt::get(I32Ty, 2*i+vi));
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vuzp");
}
case ARM::BI__builtin_neon_vzip_v:
case ARM::BI__builtin_neon_vzipq_v: {
const llvm::Type *I32Ty = llvm::Type::getInt32Ty(VMContext);
SmallVector<Constant*, 32> Indices;
unsigned nElts = cast<llvm::VectorType>(Ty)->getNumElements();
for (unsigned i = 0; i != nElts; ++i) {
Indices.push_back(ConstantInt::get(I32Ty, i));
Indices.push_back(ConstantInt::get(I32Ty, i+nElts));
}
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vzip");
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions lib/Headers/arm_neon.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def OP_XOR : Op;
def OP_ANDN : Op;
def OP_ORN : Op;
def OP_CAST : Op;
def OP_HI : Op;
def OP_LO : Op;
def OP_CONC : Op;
def OP_DUP : Op;

Expand Down Expand Up @@ -234,8 +236,8 @@ def VCOMBINE : Inst<"kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;

////////////////////////////////////////////////////////////////////////////////
// E.3.21 Splitting vectors
def VGET_HIGH : WInst<"dk", "csilhfUcUsUiUlPcPs">;
def VGET_LOW : WInst<"dk", "csilhfUcUsUiUlPcPs">;
def VGET_HIGH : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_HI>;
def VGET_LOW : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_LO>;

////////////////////////////////////////////////////////////////////////////////
// E.3.22 Converting vectors
Expand Down
23 changes: 22 additions & 1 deletion lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,28 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}

bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// TODO: verify NEON intrinsic constant args.
llvm::APSInt Result;

switch (BuiltinID) {
case ARM::BI__builtin_neon_vget_lane_i8:
case ARM::BI__builtin_neon_vget_lane_i16:
case ARM::BI__builtin_neon_vget_lane_i32:
case ARM::BI__builtin_neon_vget_lane_f32:
case ARM::BI__builtin_neon_vget_lane_i64:
case ARM::BI__builtin_neon_vgetq_lane_i8:
case ARM::BI__builtin_neon_vgetq_lane_i16:
case ARM::BI__builtin_neon_vgetq_lane_i32:
case ARM::BI__builtin_neon_vgetq_lane_f32:
case ARM::BI__builtin_neon_vgetq_lane_i64:
// Check constant-ness first.
if (SemaBuiltinConstantArg(TheCall, 1, Result))
return true;
break;
}

// Now, range check values.
//unsigned lower = 0, upper = 0;

return false;
}

Expand Down

0 comments on commit 1c2a88c

Please sign in to comment.