Index: include/clang/Basic/BuiltinsPPC.def =================================================================== --- include/clang/Basic/BuiltinsPPC.def +++ include/clang/Basic/BuiltinsPPC.def @@ -421,6 +421,7 @@ BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "") BUILTIN(__builtin_vsx_xxpermdi, "v.", "t") +BUILTIN(__builtin_vsx_xxsldwi, "v.", "t") // HTM builtins BUILTIN(__builtin_tbegin, "UiUIi", "") Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -8507,6 +8507,92 @@ Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask); return ShuffleCall; } + + case PPC::BI__builtin_vsx_xxsldwi: { + // Third argument is a compile time constant int. It must be clamped to + // to the range [0, 3]. + ConstantInt *ArgCI = dyn_cast(Ops[2]); + assert(ArgCI && "Third arg must be constant integer!"); + const int64_t MaxIndex = 3; + int64_t Index = clamp(ArgCI->getSExtValue(), 0, MaxIndex); + Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4)); + Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int32Ty, 4)); + + // Create a shuffle mask(ElemIdx0, ElemIdx1) + unsigned int ElemIdx0; + unsigned int ElemIdx1; + unsigned int ElemIdx2; + unsigned int ElemIdx3; + if (getTarget().isLittleEndian()) { + switch (Index) { + case 0: + ElemIdx0 = 0; + ElemIdx1 = 1; + ElemIdx2 = 2; + ElemIdx3 = 3; + break; + case 1: + ElemIdx0 = 7; + ElemIdx1 = 0; + ElemIdx2 = 1; + ElemIdx3 = 2; + break; + case 2: + ElemIdx0 = 6; + ElemIdx1 = 7; + ElemIdx2 = 0; + ElemIdx3 = 1; + break; + case 3: + ElemIdx0 = 5; + ElemIdx1 = 6; + ElemIdx2 = 7; + ElemIdx3 = 0; + break; + default: + llvm_unreachable("Wrong argument value!"); + } + } else { // BigEndian + switch (Index) { + case 0: + ElemIdx0 = 0; + ElemIdx1 = 1; + ElemIdx2 = 2; + ElemIdx3 = 3; + break; + case 1: + ElemIdx0 = 1; + ElemIdx1 = 2; + ElemIdx2 = 3; + ElemIdx3 = 4; + break; + case 2: + ElemIdx0 = 2; + ElemIdx1 = 3; + ElemIdx2 = 4; + ElemIdx3 = 5; + break; + case 3: + ElemIdx0 = 3; + ElemIdx1 = 4; + ElemIdx2 = 5; + ElemIdx3 = 6; + break; + default: + llvm_unreachable("Wrong argument value!"); + } + } + + Constant *ShuffleElts[4] = { ConstantInt::get(Int32Ty, ElemIdx0), + ConstantInt::get(Int32Ty, ElemIdx1), + ConstantInt::get(Int32Ty, ElemIdx2), + ConstantInt::get(Int32Ty, ElemIdx3) + }; + Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts); + + Value *ShuffleCall = Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask); + return ShuffleCall; + } } } Index: lib/Headers/altivec.h =================================================================== --- lib/Headers/altivec.h +++ lib/Headers/altivec.h @@ -12158,6 +12158,7 @@ #ifdef __VSX__ #define vec_xxpermdi __builtin_vsx_xxpermdi +#define vec_xxsldwi __builtin_vsx_xxsldwi #endif /* vec_xor */ Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -1697,6 +1697,7 @@ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) || SemaBuiltinConstantArgRange(TheCall, 2, 0, 31); case PPC::BI__builtin_vsx_xxpermdi: + case PPC::BI__builtin_vsx_xxsldwi: return SemaBuiltinVSX(TheCall, 3); } return SemaBuiltinConstantArgRange(TheCall, i, l, u); Index: test/CodeGen/builtins-ppc-error.c =================================================================== --- test/CodeGen/builtins-ppc-error.c +++ test/CodeGen/builtins-ppc-error.c @@ -27,3 +27,12 @@ vec_xxpermdi(vsi, vsi, -1); //expected-error {{third argument to '__builtin_vsx_xxpermdi' must be a constant integer between 0-3}} vec_xxpermdi(vsi, vuc, 2); //expected-error {{first two arguments to '__builtin_vsx_xxpermdi' must be the same type}} } + +void testXXSLDWI(void) { + int index = 5; + vec_xxsldwi(vsi); //expected-error {{too few arguments to function call, expected at least 3, have 1}} + vec_xxsldwi(vsi, vsi, 2, 4); //expected-error {{too many arguments to function call, expected at most 3, have 4}} + vec_xxsldwi(vsi, vsi, index); //expected-error {{third argument to '__builtin_vsx_xxsldwi' must be a constant integer between 0-3}} + vec_xxsldwi(vsi, vsi, -1); //expected-error {{third argument to '__builtin_vsx_xxsldwi' must be a constant integer between 0-3}} + vec_xxsldwi(vsi, vuc, 2); //expected-error {{first two arguments to '__builtin_vsx_xxsldwi' must be the same type}} +} Index: test/CodeGen/builtins-ppc-vsx.c =================================================================== --- test/CodeGen/builtins-ppc-vsx.c +++ test/CodeGen/builtins-ppc-vsx.c @@ -1731,4 +1731,45 @@ res_vuc = vec_xxpermdi(vuc, vuc, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> + +res_vd = vec_xxsldwi(vd, vd, 0); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vf = vec_xxsldwi(vf, vf, 1); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vsll = vec_xxsldwi(vsll, vsll, 2); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vull = vec_xxsldwi(vull, vull, 3); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vsi = vec_xxsldwi(vsi, vsi, 0); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vui = vec_xxsldwi(vui, vui, 1); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vss = vec_xxsldwi(vss, vss, 2); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + + +res_vus = vec_xxsldwi(vus, vus, 3); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vsc = vec_xxsldwi(vsc, vsc, 0); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> + +res_vuc = vec_xxsldwi(vuc, vuc, 1); +// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> +// CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> }