зеркало из https://github.com/microsoft/clang-1.git
comparison of AltiVec vectors now gives bool result (fix for 7533)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119678 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
cdba6595a6
Коммит
aa4fe05939
|
@ -1981,6 +1981,48 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
|
|||
return Builder.CreateAShr(Ops.LHS, RHS, "shr");
|
||||
}
|
||||
|
||||
enum IntrinsicType { VCMPEQ, VCMPGT };
|
||||
// return corresponding comparison intrinsic for given vector type
|
||||
static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT,
|
||||
BuiltinType::Kind ElemKind) {
|
||||
switch (ElemKind) {
|
||||
default: assert(0 && "unexpected element type");
|
||||
case BuiltinType::Char_U:
|
||||
case BuiltinType::UChar:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtub_p;
|
||||
break;
|
||||
case BuiltinType::Char_S:
|
||||
case BuiltinType::SChar:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtsb_p;
|
||||
break;
|
||||
case BuiltinType::UShort:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtuh_p;
|
||||
break;
|
||||
case BuiltinType::Short:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtsh_p;
|
||||
break;
|
||||
case BuiltinType::UInt:
|
||||
case BuiltinType::ULong:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtuw_p;
|
||||
break;
|
||||
case BuiltinType::Int:
|
||||
case BuiltinType::Long:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtsw_p;
|
||||
break;
|
||||
case BuiltinType::Float:
|
||||
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpeqfp_p :
|
||||
llvm::Intrinsic::ppc_altivec_vcmpgtfp_p;
|
||||
break;
|
||||
}
|
||||
return llvm::Intrinsic::not_intrinsic;
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
|
||||
unsigned SICmpOpc, unsigned FCmpOpc) {
|
||||
TestAndClearIgnoreResultAssign();
|
||||
|
@ -1997,6 +2039,72 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
|
|||
Value *LHS = Visit(E->getLHS());
|
||||
Value *RHS = Visit(E->getRHS());
|
||||
|
||||
// If AltiVec, the comparison results in a numeric type, so we use
|
||||
// intrinsics comparing vectors and giving 0 or 1 as a result
|
||||
if (LHSTy->isVectorType() && CGF.getContext().getLangOptions().AltiVec) {
|
||||
// constants for mapping CR6 register bits to predicate result
|
||||
enum { CR6_EQ=0, CR6_EQ_REV, CR6_LT, CR6_LT_REV } CR6;
|
||||
|
||||
llvm::Intrinsic::ID ID = llvm::Intrinsic::not_intrinsic;
|
||||
|
||||
// in several cases vector arguments order will be reversed
|
||||
Value *FirstVecArg = LHS,
|
||||
*SecondVecArg = RHS;
|
||||
|
||||
QualType ElTy = LHSTy->getAs<VectorType>()->getElementType();
|
||||
Type *Ty = CGF.getContext().getCanonicalType(ElTy).getTypePtr();
|
||||
const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty);
|
||||
BuiltinType::Kind ElementKind = BTy->getKind();
|
||||
|
||||
switch(E->getOpcode()) {
|
||||
default: assert(0 && "is not a comparison operation");
|
||||
case BO_EQ:
|
||||
CR6 = CR6_LT;
|
||||
ID = GetIntrinsic(VCMPEQ, ElementKind);
|
||||
break;
|
||||
case BO_NE:
|
||||
CR6 = CR6_EQ;
|
||||
ID = GetIntrinsic(VCMPEQ, ElementKind);
|
||||
break;
|
||||
case BO_LT:
|
||||
CR6 = CR6_LT;
|
||||
ID = GetIntrinsic(VCMPGT, ElementKind);
|
||||
std::swap(FirstVecArg, SecondVecArg);
|
||||
break;
|
||||
case BO_GT:
|
||||
CR6 = CR6_LT;
|
||||
ID = GetIntrinsic(VCMPGT, ElementKind);
|
||||
break;
|
||||
case BO_LE:
|
||||
if (ElementKind == BuiltinType::Float) {
|
||||
CR6 = CR6_LT;
|
||||
ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p;
|
||||
std::swap(FirstVecArg, SecondVecArg);
|
||||
}
|
||||
else {
|
||||
CR6 = CR6_EQ;
|
||||
ID = GetIntrinsic(VCMPGT, ElementKind);
|
||||
}
|
||||
break;
|
||||
case BO_GE:
|
||||
if (ElementKind == BuiltinType::Float) {
|
||||
CR6 = CR6_LT;
|
||||
ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p;
|
||||
}
|
||||
else {
|
||||
CR6 = CR6_EQ;
|
||||
ID = GetIntrinsic(VCMPGT, ElementKind);
|
||||
std::swap(FirstVecArg, SecondVecArg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Value *CR6Param = llvm::ConstantInt::get(CGF.Int32Ty, CR6);
|
||||
llvm::Function *F = CGF.CGM.getIntrinsic(ID);
|
||||
Result = Builder.CreateCall3(F, CR6Param, FirstVecArg, SecondVecArg, "");
|
||||
return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
|
||||
}
|
||||
|
||||
if (LHS->getType()->isFPOrFPVectorTy()) {
|
||||
Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc,
|
||||
LHS, RHS, "cmp");
|
||||
|
|
|
@ -6423,6 +6423,11 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
|
|||
if (vType.isNull())
|
||||
return vType;
|
||||
|
||||
// If AltiVec, the comparison results in a numeric type, i.e.
|
||||
// bool for C++, int for C
|
||||
if (getLangOptions().AltiVec)
|
||||
return (getLangOptions().CPlusPlus ? Context.BoolTy : Context.IntTy);
|
||||
|
||||
QualType lType = lex->getType();
|
||||
QualType rType = rex->getType();
|
||||
|
||||
|
|
|
@ -3052,3 +3052,64 @@ void test6() {
|
|||
/* vec_any_out */
|
||||
res_i = vec_any_out(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp.p
|
||||
}
|
||||
|
||||
/* ------------------------------ Relational Operators------------------------------- */
|
||||
// CHECK: define void @test7
|
||||
void test7() {
|
||||
vector signed char vsc1 = (vector signed char)(-1);
|
||||
vector signed char vsc2 = (vector signed char)(-2);
|
||||
res_i = (vsc1 == vsc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 2
|
||||
res_i = (vsc1 != vsc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 0
|
||||
res_i = (vsc1 < vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 2
|
||||
res_i = (vsc1 > vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 2
|
||||
res_i = (vsc1 <= vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 0
|
||||
res_i = (vsc1 >= vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 0
|
||||
vector unsigned char vuc1 = (vector unsigned char)(1);
|
||||
vector unsigned char vuc2 = (vector unsigned char)(2);
|
||||
res_i = (vuc1 == vuc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 2
|
||||
res_i = (vuc1 != vuc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 0
|
||||
res_i = (vuc1 < vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 2
|
||||
res_i = (vuc1 > vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 2
|
||||
res_i = (vuc1 <= vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 0
|
||||
res_i = (vuc1 >= vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 0
|
||||
vector short vs1 = (vector short)(-1);
|
||||
vector short vs2 = (vector short)(-2);
|
||||
res_i = (vs1 == vs2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 2
|
||||
res_i = (vs1 != vs2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 0
|
||||
res_i = (vs1 < vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 2
|
||||
res_i = (vs1 > vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 2
|
||||
res_i = (vs1 <= vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 0
|
||||
res_i = (vs1 >= vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 0
|
||||
vector unsigned short vus1 = (vector unsigned short)(1);
|
||||
vector unsigned short vus2 = (vector unsigned short)(2);
|
||||
res_i = (vus1 == vus2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 2
|
||||
res_i = (vus1 != vus2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 0
|
||||
res_i = (vus1 < vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 2
|
||||
res_i = (vus1 > vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 2
|
||||
res_i = (vus1 <= vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 0
|
||||
res_i = (vus1 >= vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 0
|
||||
vector int vi1 = (vector int)(-1);
|
||||
vector int vi2 = (vector int)(-2);
|
||||
res_i = (vi1 == vi2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 2
|
||||
res_i = (vi1 != vi2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 0
|
||||
res_i = (vi1 < vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 2
|
||||
res_i = (vi1 > vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 2
|
||||
res_i = (vi1 <= vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 0
|
||||
res_i = (vi1 >= vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 0
|
||||
vector unsigned int vui1 = (vector unsigned int)(1);
|
||||
vector unsigned int vui2 = (vector unsigned int)(2);
|
||||
res_i = (vui1 == vui2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 2
|
||||
res_i = (vui1 != vui2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 0
|
||||
res_i = (vui1 < vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 2
|
||||
res_i = (vui1 > vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 2
|
||||
res_i = (vui1 <= vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 0
|
||||
res_i = (vui1 >= vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 0
|
||||
vector float vf1 = (vector float)(1.0);
|
||||
vector float vf2 = (vector float)(2.0);
|
||||
res_i = (vf1 == vf2); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p(i32 2
|
||||
res_i = (vf1 != vf2); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p(i32 0
|
||||
res_i = (vf1 < vf2); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p(i32 2
|
||||
res_i = (vf1 > vf2); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p(i32 2
|
||||
res_i = (vf1 <= vf2); // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2
|
||||
res_i = (vf1 >= vf2); // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2
|
||||
}
|
||||
|
|
|
@ -100,6 +100,16 @@ void f() {
|
|||
__vector unsigned int tv = gccv;
|
||||
gccv = v;
|
||||
gccvector unsigned int tgv = v;
|
||||
|
||||
int res_i;
|
||||
// bug 7553 - Problem with '==' and vectors
|
||||
res_i = (vv_sc == vv_sc);
|
||||
res_i = (vv_uc != vv_uc);
|
||||
res_i = (vv_s > vv_s);
|
||||
res_i = (vv_us >= vv_us);
|
||||
res_i = (vv_i < vv_i);
|
||||
res_i = (vv_ui <= vv_ui);
|
||||
res_i = (vv_f <= vv_f);
|
||||
}
|
||||
|
||||
// bug 6895 - Vectorl literal casting confusion.
|
||||
|
|
|
@ -127,27 +127,17 @@ vector int v4 = (vector int)(1, 2, 3, 4);
|
|||
vector float v5 = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
vector char v6 = (vector char)((vector int)(1+2, -2, (int)(2.0 * 3), -(5-3)));
|
||||
|
||||
#if 0 // Not ready yet.
|
||||
// bug 7553 - Problem with '==' and vectors
|
||||
void func() {
|
||||
vector int v10i = (vector int)(1, 2, 3, 4);
|
||||
vector int v11i = (vector int)(1, 2, 3, 4);
|
||||
bool r10ieq = (v10i == v11i);
|
||||
bool r10ine = (v10i != v11i);
|
||||
bool r10igt = (v10i > v11i);
|
||||
bool r10ige = (v10i >= v11i);
|
||||
bool r10ilt = (v10i < v11i);
|
||||
bool r10ile = (v10i <= v11i);
|
||||
vector float v10f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
vector float v11f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
bool r10feq = (v10f == v11f);
|
||||
bool r10fne = (v10f != v11f);
|
||||
bool r10fgt = (v10f > v11f);
|
||||
bool r10fge = (v10f >= v11f);
|
||||
bool r10flt = (v10f < v11f);
|
||||
bool r10fle = (v10f <= v11f);
|
||||
bool res_b;
|
||||
res_b = (vv_sc == vv_sc);
|
||||
res_b = (vv_uc != vv_uc);
|
||||
res_b = (vv_s > vv_s);
|
||||
res_b = (vv_us >= vv_us);
|
||||
res_b = (vv_i < vv_i);
|
||||
res_b = (vv_ui <= vv_ui);
|
||||
res_b = (vv_f <= vv_f);
|
||||
}
|
||||
#endif
|
||||
|
||||
// vecreturn attribute test
|
||||
struct Vector
|
||||
|
|
|
@ -30,6 +30,6 @@ void test()
|
|||
|
||||
f(vAltiVec);
|
||||
vGCC = vAltiVec;
|
||||
vGCC = vGCC > vAltiVec;
|
||||
int res = vGCC > vAltiVec;
|
||||
vAltiVec = 0 ? vGCC : vGCC;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,6 @@ void test()
|
|||
|
||||
f(vAltiVec);
|
||||
vGCC = vAltiVec;
|
||||
vGCC = vGCC > vAltiVec;
|
||||
bool res = vGCC > vAltiVec;
|
||||
vAltiVec = 0 ? vGCC : vGCC;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче