Skip to content

Commit 51cad04

Browse files
cdisselkoenefriedma-quic
authored andcommitted
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 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
1 parent 48961ba commit 51cad04

File tree

5 files changed

+119
-17
lines changed

5 files changed

+119
-17
lines changed

llvm/include/llvm-c/Core.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3636,7 +3636,7 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
36363636
/* Get the number of clauses on the landingpad instruction */
36373637
unsigned LLVMGetNumClauses(LLVMValueRef LandingPad);
36383638

3639-
/* Get the value of the clause at idnex Idx on the landingpad instruction */
3639+
/* Get the value of the clause at index Idx on the landingpad instruction */
36403640
LLVMValueRef LLVMGetClause(LLVMValueRef LandingPad, unsigned Idx);
36413641

36423642
/* Add a catch or filter clause to the landingpad instruction */
@@ -3937,6 +3937,19 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
39373937
LLVMAtomicOrdering FailureOrdering,
39383938
LLVMBool SingleThread);
39393939

3940+
/**
3941+
* Get the number of elements in the mask of a ShuffleVector instruction.
3942+
*/
3943+
unsigned LLVMGetNumMaskElements(LLVMValueRef ShuffleVectorInst);
3944+
3945+
/**
3946+
* Get the mask value at position Elt in the mask of a ShuffleVector
3947+
* instruction. Return LLVMUndefMaskElem if the mask value is undef at that
3948+
* position.
3949+
*/
3950+
int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt);
3951+
extern const int LLVMUndefMaskElem;
3952+
39403953
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
39413954
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
39423955

llvm/lib/IR/Core.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3952,6 +3952,20 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
39523952
singleThread ? SyncScope::SingleThread : SyncScope::System));
39533953
}
39543954

3955+
unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) {
3956+
Value *P = unwrap<Value>(SVInst);
3957+
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
3958+
return I->getShuffleMask().size();
3959+
}
3960+
3961+
int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
3962+
Value *P = unwrap<Value>(SVInst);
3963+
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
3964+
return I->getMaskValue(Elt);
3965+
}
3966+
const int LLVMUndefMaskElem =
3967+
-1; // not actually accessible as ShuffleVectorInst::UndefMaskElem, so we
3968+
// hardcode it here
39553969

39563970
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
39573971
Value *P = unwrap<Value>(AtomicInst);

llvm/test/Bindings/llvm-c/echo.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,24 @@ define void @memops(i8* %ptr) {
156156
ret void
157157
}
158158

159+
define i32 @vectorops(i32, i32) {
160+
%a = insertelement <4 x i32> undef, i32 %0, i32 0
161+
%b = insertelement <4 x i32> %a, i32 %1, i32 2
162+
%c = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer
163+
%d = shufflevector <4 x i32> %c, <4 x i32> %b, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
164+
%e = add <4 x i32> %d, %a
165+
%f = mul <4 x i32> %e, %b
166+
%g = xor <4 x i32> %f, %d
167+
%h = or <4 x i32> %f, %e
168+
%i = lshr <4 x i32> %h, <i32 2, i32 2, i32 2, i32 2>
169+
%j = shl <4 x i32> %i, <i32 2, i32 3, i32 4, i32 5>
170+
%k = shufflevector <4 x i32> %j, <4 x i32> %i, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
171+
%m = shufflevector <4 x i32> %k, <4 x i32> undef, <1 x i32> <i32 1>
172+
%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>
173+
%p = extractelement <8 x i32> %n, i32 5
174+
ret i32 %p
175+
}
176+
159177
declare void @personalityFn()
160178

161179
define void @exn() personality void ()* @personalityFn {

llvm/tools/llvm-c-test/echo.cpp

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ template<typename T>
3030
struct CAPIDenseMap {};
3131

3232
// The default DenseMapInfo require to know about pointer alignment.
33-
// Because the C API uses opaques pointer types, their alignment is unknown.
33+
// Because the C API uses opaque pointer types, their alignment is unknown.
3434
// As a result, we need to roll out our own implementation.
3535
template<typename T>
3636
struct CAPIDenseMap<T*> {
@@ -306,7 +306,7 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
306306
return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
307307
}
308308

309-
// Try contant data array
309+
// Try constant data array
310310
if (LLVMIsAConstantDataArray(Cst)) {
311311
check_value_kind(Cst, LLVMConstantDataArrayValueKind);
312312
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
@@ -357,9 +357,32 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
357357
report_fatal_error("ConstantFP is not supported");
358358
}
359359

360-
// This kind of constant is not supported
360+
// Try ConstantVector
361+
if (LLVMIsAConstantVector(Cst)) {
362+
check_value_kind(Cst, LLVMConstantVectorValueKind);
363+
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
364+
unsigned EltCount = LLVMGetVectorSize(Ty);
365+
SmallVector<LLVMValueRef, 8> Elts;
366+
for (unsigned i = 0; i < EltCount; i++)
367+
Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
368+
return LLVMConstVector(Elts.data(), EltCount);
369+
}
370+
371+
// Try ConstantDataVector
372+
if (LLVMIsAConstantDataVector(Cst)) {
373+
check_value_kind(Cst, LLVMConstantDataVectorValueKind);
374+
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
375+
unsigned EltCount = LLVMGetVectorSize(Ty);
376+
SmallVector<LLVMValueRef, 8> Elts;
377+
for (unsigned i = 0; i < EltCount; i++)
378+
Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M));
379+
return LLVMConstVector(Elts.data(), EltCount);
380+
}
381+
382+
// At this point, if it's not a constant expression, it's a kind of constant
383+
// which is not supported
361384
if (!LLVMIsAConstantExpr(Cst))
362-
report_fatal_error("Expected a constant expression");
385+
report_fatal_error("Unsupported constant kind");
363386

364387
// At this point, it must be a constant expression
365388
check_value_kind(Cst, LLVMConstantExprValueKind);
@@ -370,7 +393,8 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
370393
return LLVMConstBitCast(clone_constant(LLVMGetOperand(Cst, 0), M),
371394
TypeCloner(M).Clone(Cst));
372395
default:
373-
fprintf(stderr, "%d is not a supported opcode\n", Op);
396+
fprintf(stderr, "%d is not a supported opcode for constant expressions\n",
397+
Op);
374398
exit(-1);
375399
}
376400
}
@@ -443,7 +467,7 @@ struct FunCloner {
443467
auto i = VMap.find(Src);
444468
if (i != VMap.end()) {
445469
// If we have a hit, it means we already generated the instruction
446-
// as a dependancy to somethign else. We need to make sure
470+
// as a dependency to something else. We need to make sure
447471
// it is ordered properly.
448472
auto I = i->second;
449473
LLVMInstructionRemoveFromParent(I);
@@ -746,21 +770,55 @@ struct FunCloner {
746770
}
747771
case LLVMExtractValue: {
748772
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
749-
if (LLVMGetNumIndices(Src) != 1)
750-
report_fatal_error("Expected only one indice");
773+
if (LLVMGetNumIndices(Src) > 1)
774+
report_fatal_error("ExtractValue: Expected only one index");
775+
else if (LLVMGetNumIndices(Src) < 1)
776+
report_fatal_error("ExtractValue: Expected an index");
751777
auto I = LLVMGetIndices(Src)[0];
752778
Dst = LLVMBuildExtractValue(Builder, Agg, I, Name);
753779
break;
754780
}
755781
case LLVMInsertValue: {
756782
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
757783
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
758-
if (LLVMGetNumIndices(Src) != 1)
759-
report_fatal_error("Expected only one indice");
784+
if (LLVMGetNumIndices(Src) > 1)
785+
report_fatal_error("InsertValue: Expected only one index");
786+
else if (LLVMGetNumIndices(Src) < 1)
787+
report_fatal_error("InsertValue: Expected an index");
760788
auto I = LLVMGetIndices(Src)[0];
761789
Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
762790
break;
763791
}
792+
case LLVMExtractElement: {
793+
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
794+
LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 1));
795+
Dst = LLVMBuildExtractElement(Builder, Agg, Index, Name);
796+
break;
797+
}
798+
case LLVMInsertElement: {
799+
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
800+
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
801+
LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 2));
802+
Dst = LLVMBuildInsertElement(Builder, Agg, V, Index, Name);
803+
break;
804+
}
805+
case LLVMShuffleVector: {
806+
LLVMValueRef Agg0 = CloneValue(LLVMGetOperand(Src, 0));
807+
LLVMValueRef Agg1 = CloneValue(LLVMGetOperand(Src, 1));
808+
SmallVector<LLVMValueRef, 8> MaskElts;
809+
unsigned NumMaskElts = LLVMGetNumMaskElements(Src);
810+
for (unsigned i = 0; i < NumMaskElts; i++) {
811+
int Val = LLVMGetMaskValue(Src, i);
812+
if (Val == LLVMUndefMaskElem) {
813+
MaskElts.push_back(LLVMGetUndef(LLVMInt64Type()));
814+
} else {
815+
MaskElts.push_back(LLVMConstInt(LLVMInt64Type(), Val, true));
816+
}
817+
}
818+
LLVMValueRef Mask = LLVMConstVector(MaskElts.data(), NumMaskElts);
819+
Dst = LLVMBuildShuffleVector(Builder, Agg0, Agg1, Mask, Name);
820+
break;
821+
}
764822
case LLVMFreeze: {
765823
LLVMValueRef Arg = CloneValue(LLVMGetOperand(Src, 0));
766824
Dst = LLVMBuildFreeze(Builder, Arg, Name);
@@ -1102,7 +1160,7 @@ static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
11021160
LLVMGlobalSetMetadata(G, Kind, MD);
11031161
}
11041162
LLVMDisposeValueMetadataEntries(AllMetadata);
1105-
1163+
11061164
LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur));
11071165
LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur));
11081166
LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur));

llvm/tools/llvm-c-test/main.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ static void print_usage(void) {
3636
fprintf(stderr, " * --targets-list\n");
3737
fprintf(stderr, " List available targets\n\n");
3838
fprintf(stderr, " * --object-list-sections\n");
39-
fprintf(stderr, " Read object file form stdin - list sections\n\n");
39+
fprintf(stderr, " Read object file from stdin - list sections\n\n");
4040
fprintf(stderr, " * --object-list-symbols\n");
4141
fprintf(stderr,
42-
" Read object file form stdin - list symbols (like nm)\n\n");
42+
" Read object file from stdin - list symbols (like nm)\n\n");
4343
fprintf(stderr, " * --disassemble\n");
4444
fprintf(stderr, " Read lines of triple, hex ascii machine code from stdin "
4545
"- print disassembly\n\n");
@@ -48,11 +48,10 @@ static void print_usage(void) {
4848
stderr,
4949
" Read lines of name, rpn from stdin - print generated module\n\n");
5050
fprintf(stderr, " * --echo\n");
51-
fprintf(stderr,
52-
" Read bitcode file form stdin - print it back out\n\n");
51+
fprintf(stderr, " Read bitcode file from stdin - print it back out\n\n");
5352
fprintf(stderr, " * --test-diagnostic-handler\n");
5453
fprintf(stderr,
55-
" Read bitcode file form stdin with a diagnostic handler set\n\n");
54+
" Read bitcode file from stdin with a diagnostic handler set\n\n");
5655
fprintf(stderr, " * --test-dibuilder\n");
5756
fprintf(stderr,
5857
" Run tests for the DIBuilder C API - print generated module\n\n");

0 commit comments

Comments
 (0)