Skip to content

Commit

Permalink
C API: functions to get mask of a ShuffleVector
Browse files Browse the repository at this point in the history
This commit fixes a regression (from LLVM 10 to LLVM 11 RC3) in the LLVM
C API.

Previously, commit 1ee6ec2 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 51cad04)
  • Loading branch information
cdisselkoen authored and zmodem committed Sep 28, 2020
1 parent 1e4b179 commit 9e367bd
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 17 deletions.
15 changes: 14 additions & 1 deletion llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);

Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/Bindings/llvm-c/echo.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
80 changes: 69 additions & 11 deletions llvm/tools/llvm-c-test/echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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*> {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -746,21 +770,55 @@ 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;
}
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);
Expand Down Expand Up @@ -1102,7 +1160,7 @@ static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
LLVMGlobalSetMetadata(G, Kind, MD);
}
LLVMDisposeValueMetadataEntries(AllMetadata);

LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur));
LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur));
LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur));
Expand Down
9 changes: 4 additions & 5 deletions llvm/tools/llvm-c-test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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");
Expand Down

0 comments on commit 9e367bd

Please sign in to comment.