1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

C API: functions to get mask of a ShuffleVector

This commit fixes a regression (from LLVM 10 to LLVM 11 RC3) in the LLVM
C API.

Previously, commit 1ee6ec2bf removed the mask operand from the
ShuffleVector instruction, storing the mask data separately in the
instruction instead; this reduced the number of operands of
ShuffleVector from 3 to 2. AFAICT, this change unintentionally caused
a regression in the LLVM C API. Specifically, it is no longer possible
to get the mask of a ShuffleVector instruction through the C API. This
patch introduces new functions which together allow a C API user to get
the mask of a ShuffleVector instruction, restoring the functionality
which was previously available through LLVMGetOperand().

This patch also adds tests for this change to the llvm-c-test
executable, which involved adding support for InsertElement,
ExtractElement, and ShuffleVector itself (as well as constant vectors)
to echo.cpp. Previously, vector operations weren't tested at all in
echo.ll.

I also fixed some typos in comments and help-text nearby these changes,
which I happened to spot while developing this patch. Since the typo
fixes are technically unrelated other than being in the same files, I'm
happy to take them out if you'd rather they not be included in the patch.

Differential Revision: https://reviews.llvm.org/D88190

(cherry picked from commit 51cad041e0cb26597c7ccc0fbfaa349b8fffbcda)
This commit is contained in:
Craig Disselkoen 2020-09-25 14:34:23 -07:00 committed by Hans Wennborg
parent 172c27d8f3
commit 810086af1d
5 changed files with 119 additions and 17 deletions

View File

@ -3636,7 +3636,7 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
/* Get the number of clauses on the landingpad instruction */
unsigned LLVMGetNumClauses(LLVMValueRef LandingPad);
/* Get the value of the clause at idnex Idx on the landingpad instruction */
/* Get the value of the clause at index Idx on the landingpad instruction */
LLVMValueRef LLVMGetClause(LLVMValueRef LandingPad, unsigned Idx);
/* Add a catch or filter clause to the landingpad instruction */
@ -3937,6 +3937,19 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMAtomicOrdering FailureOrdering,
LLVMBool SingleThread);
/**
* Get the number of elements in the mask of a ShuffleVector instruction.
*/
unsigned LLVMGetNumMaskElements(LLVMValueRef ShuffleVectorInst);
/**
* Get the mask value at position Elt in the mask of a ShuffleVector
* instruction. Return LLVMUndefMaskElem if the mask value is undef at that
* position.
*/
int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt);
extern const int LLVMUndefMaskElem;
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);

View File

@ -3952,6 +3952,20 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
singleThread ? SyncScope::SingleThread : SyncScope::System));
}
unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) {
Value *P = unwrap<Value>(SVInst);
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
return I->getShuffleMask().size();
}
int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
Value *P = unwrap<Value>(SVInst);
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
return I->getMaskValue(Elt);
}
const int LLVMUndefMaskElem =
-1; // not actually accessible as ShuffleVectorInst::UndefMaskElem, so we
// hardcode it here
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
Value *P = unwrap<Value>(AtomicInst);

View File

@ -156,6 +156,24 @@ define void @memops(i8* %ptr) {
ret void
}
define i32 @vectorops(i32, i32) {
%a = insertelement <4 x i32> undef, i32 %0, i32 0
%b = insertelement <4 x i32> %a, i32 %1, i32 2
%c = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer
%d = shufflevector <4 x i32> %c, <4 x i32> %b, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
%e = add <4 x i32> %d, %a
%f = mul <4 x i32> %e, %b
%g = xor <4 x i32> %f, %d
%h = or <4 x i32> %f, %e
%i = lshr <4 x i32> %h, <i32 2, i32 2, i32 2, i32 2>
%j = shl <4 x i32> %i, <i32 2, i32 3, i32 4, i32 5>
%k = shufflevector <4 x i32> %j, <4 x i32> %i, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
%m = shufflevector <4 x i32> %k, <4 x i32> undef, <1 x i32> <i32 1>
%n = shufflevector <4 x i32> %j, <4 x i32> undef, <8 x i32> <i32 0, i32 0, i32 1, i32 2, i32 undef, i32 3, i32 undef, i32 undef>
%p = extractelement <8 x i32> %n, i32 5
ret i32 %p
}
declare void @personalityFn()
define void @exn() personality void ()* @personalityFn {

View File

@ -30,7 +30,7 @@ template<typename T>
struct CAPIDenseMap {};
// The default DenseMapInfo require to know about pointer alignment.
// Because the C API uses opaques pointer types, their alignment is unknown.
// Because the C API uses opaque pointer types, their alignment is unknown.
// As a result, we need to roll out our own implementation.
template<typename T>
struct CAPIDenseMap<T*> {
@ -306,7 +306,7 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
}
// Try contant data array
// Try constant data array
if (LLVMIsAConstantDataArray(Cst)) {
check_value_kind(Cst, LLVMConstantDataArrayValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
@ -357,9 +357,32 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
report_fatal_error("ConstantFP is not supported");
}
// This kind of constant is not supported
// Try ConstantVector
if (LLVMIsAConstantVector(Cst)) {
check_value_kind(Cst, LLVMConstantVectorValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetVectorSize(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
return LLVMConstVector(Elts.data(), EltCount);
}
// Try ConstantDataVector
if (LLVMIsAConstantDataVector(Cst)) {
check_value_kind(Cst, LLVMConstantDataVectorValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetVectorSize(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M));
return LLVMConstVector(Elts.data(), EltCount);
}
// At this point, if it's not a constant expression, it's a kind of constant
// which is not supported
if (!LLVMIsAConstantExpr(Cst))
report_fatal_error("Expected a constant expression");
report_fatal_error("Unsupported constant kind");
// At this point, it must be a constant expression
check_value_kind(Cst, LLVMConstantExprValueKind);
@ -370,7 +393,8 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
return LLVMConstBitCast(clone_constant(LLVMGetOperand(Cst, 0), M),
TypeCloner(M).Clone(Cst));
default:
fprintf(stderr, "%d is not a supported opcode\n", Op);
fprintf(stderr, "%d is not a supported opcode for constant expressions\n",
Op);
exit(-1);
}
}
@ -443,7 +467,7 @@ struct FunCloner {
auto i = VMap.find(Src);
if (i != VMap.end()) {
// If we have a hit, it means we already generated the instruction
// as a dependancy to somethign else. We need to make sure
// as a dependency to something else. We need to make sure
// it is ordered properly.
auto I = i->second;
LLVMInstructionRemoveFromParent(I);
@ -746,8 +770,10 @@ struct FunCloner {
}
case LLVMExtractValue: {
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
if (LLVMGetNumIndices(Src) != 1)
report_fatal_error("Expected only one indice");
if (LLVMGetNumIndices(Src) > 1)
report_fatal_error("ExtractValue: Expected only one index");
else if (LLVMGetNumIndices(Src) < 1)
report_fatal_error("ExtractValue: Expected an index");
auto I = LLVMGetIndices(Src)[0];
Dst = LLVMBuildExtractValue(Builder, Agg, I, Name);
break;
@ -755,12 +781,44 @@ struct FunCloner {
case LLVMInsertValue: {
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
if (LLVMGetNumIndices(Src) != 1)
report_fatal_error("Expected only one indice");
if (LLVMGetNumIndices(Src) > 1)
report_fatal_error("InsertValue: Expected only one index");
else if (LLVMGetNumIndices(Src) < 1)
report_fatal_error("InsertValue: Expected an index");
auto I = LLVMGetIndices(Src)[0];
Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
break;
}
case LLVMExtractElement: {
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 1));
Dst = LLVMBuildExtractElement(Builder, Agg, Index, Name);
break;
}
case LLVMInsertElement: {
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 2));
Dst = LLVMBuildInsertElement(Builder, Agg, V, Index, Name);
break;
}
case LLVMShuffleVector: {
LLVMValueRef Agg0 = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef Agg1 = CloneValue(LLVMGetOperand(Src, 1));
SmallVector<LLVMValueRef, 8> MaskElts;
unsigned NumMaskElts = LLVMGetNumMaskElements(Src);
for (unsigned i = 0; i < NumMaskElts; i++) {
int Val = LLVMGetMaskValue(Src, i);
if (Val == LLVMUndefMaskElem) {
MaskElts.push_back(LLVMGetUndef(LLVMInt64Type()));
} else {
MaskElts.push_back(LLVMConstInt(LLVMInt64Type(), Val, true));
}
}
LLVMValueRef Mask = LLVMConstVector(MaskElts.data(), NumMaskElts);
Dst = LLVMBuildShuffleVector(Builder, Agg0, Agg1, Mask, Name);
break;
}
case LLVMFreeze: {
LLVMValueRef Arg = CloneValue(LLVMGetOperand(Src, 0));
Dst = LLVMBuildFreeze(Builder, Arg, Name);

View File

@ -36,10 +36,10 @@ static void print_usage(void) {
fprintf(stderr, " * --targets-list\n");
fprintf(stderr, " List available targets\n\n");
fprintf(stderr, " * --object-list-sections\n");
fprintf(stderr, " Read object file form stdin - list sections\n\n");
fprintf(stderr, " Read object file from stdin - list sections\n\n");
fprintf(stderr, " * --object-list-symbols\n");
fprintf(stderr,
" Read object file form stdin - list symbols (like nm)\n\n");
" Read object file from stdin - list symbols (like nm)\n\n");
fprintf(stderr, " * --disassemble\n");
fprintf(stderr, " Read lines of triple, hex ascii machine code from stdin "
"- print disassembly\n\n");
@ -48,11 +48,10 @@ static void print_usage(void) {
stderr,
" Read lines of name, rpn from stdin - print generated module\n\n");
fprintf(stderr, " * --echo\n");
fprintf(stderr,
" Read bitcode file form stdin - print it back out\n\n");
fprintf(stderr, " Read bitcode file from stdin - print it back out\n\n");
fprintf(stderr, " * --test-diagnostic-handler\n");
fprintf(stderr,
" Read bitcode file form stdin with a diagnostic handler set\n\n");
" Read bitcode file from stdin with a diagnostic handler set\n\n");
fprintf(stderr, " * --test-dibuilder\n");
fprintf(stderr,
" Run tests for the DIBuilder C API - print generated module\n\n");