Skip to content

Commit bbda4af

Browse files
thurstondNoumanAmir657
authored andcommitted
[msan] Add handleIntrinsicByApplyingToShadow; support NEON tbl/tbx (llvm#114490)
This adds a general function that handles intrinsics by applying the intrinsic to the shadows, and applies it to the specific case of Arm NEON TBL/TBX intrinsics. This also updates the tests from llvm#114462
1 parent 55371cc commit bbda4af

File tree

2 files changed

+173
-236
lines changed

2 files changed

+173
-236
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -3944,6 +3944,56 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
39443944
}
39453945
}
39463946

3947+
/// Handle intrinsics by applying the intrinsic to the shadows.
3948+
///
3949+
/// The trailing arguments are passed verbatim to the intrinsic, though any
3950+
/// uninitialized trailing arguments can also taint the shadow e.g., for an
3951+
/// intrinsic with one trailing verbatim argument:
3952+
/// out = intrinsic(var1, var2, opType)
3953+
/// we compute:
3954+
/// shadow[out] =
3955+
/// intrinsic(shadow[var1], shadow[var2], opType) | shadow[opType]
3956+
///
3957+
/// For example, this can be applied to the Arm NEON vector table intrinsics
3958+
/// (tbl{1,2,3,4}).
3959+
///
3960+
/// The origin is approximated using setOriginForNaryOp.
3961+
void handleIntrinsicByApplyingToShadow(IntrinsicInst &I,
3962+
unsigned int trailingVerbatimArgs) {
3963+
IRBuilder<> IRB(&I);
3964+
3965+
assert(trailingVerbatimArgs < I.arg_size());
3966+
3967+
SmallVector<Value *, 8> ShadowArgs;
3968+
// Don't use getNumOperands() because it includes the callee
3969+
for (unsigned int i = 0; i < I.arg_size() - trailingVerbatimArgs; i++) {
3970+
Value *Shadow = getShadow(&I, i);
3971+
ShadowArgs.push_back(Shadow);
3972+
}
3973+
3974+
for (unsigned int i = I.arg_size() - trailingVerbatimArgs; i < I.arg_size();
3975+
i++) {
3976+
Value *Arg = I.getArgOperand(i);
3977+
ShadowArgs.push_back(Arg);
3978+
}
3979+
3980+
CallInst *CI =
3981+
IRB.CreateIntrinsic(I.getType(), I.getIntrinsicID(), ShadowArgs);
3982+
Value *CombinedShadow = CI;
3983+
3984+
// Combine the computed shadow with the shadow of trailing args
3985+
for (unsigned int i = I.arg_size() - trailingVerbatimArgs; i < I.arg_size();
3986+
i++) {
3987+
Value *Shadow =
3988+
CreateShadowCast(IRB, getShadow(&I, i), CombinedShadow->getType());
3989+
CombinedShadow = IRB.CreateOr(Shadow, CombinedShadow, "_msprop");
3990+
}
3991+
3992+
setShadow(&I, CombinedShadow);
3993+
3994+
setOriginForNaryOp(I);
3995+
}
3996+
39473997
void visitIntrinsicInst(IntrinsicInst &I) {
39483998
switch (I.getIntrinsicID()) {
39493999
case Intrinsic::uadd_with_overflow:
@@ -4319,6 +4369,28 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
43194369
break;
43204370
}
43214371

4372+
// Arm NEON vector table intrinsics have the source/table register(s) as
4373+
// arguments, followed by the index register. They return the output.
4374+
//
4375+
// 'TBL writes a zero if an index is out-of-range, while TBX leaves the
4376+
// original value unchanged in the destination register.'
4377+
// Conveniently, zero denotes a clean shadow, which means out-of-range
4378+
// indices for TBL will initialize the user data with zero and also clean
4379+
// the shadow. (For TBX, neither the user data nor the shadow will be
4380+
// updated, which is also correct.)
4381+
case Intrinsic::aarch64_neon_tbl1:
4382+
case Intrinsic::aarch64_neon_tbl2:
4383+
case Intrinsic::aarch64_neon_tbl3:
4384+
case Intrinsic::aarch64_neon_tbl4:
4385+
case Intrinsic::aarch64_neon_tbx1:
4386+
case Intrinsic::aarch64_neon_tbx2:
4387+
case Intrinsic::aarch64_neon_tbx3:
4388+
case Intrinsic::aarch64_neon_tbx4: {
4389+
// The last trailing argument (index register) should be handled verbatim
4390+
handleIntrinsicByApplyingToShadow(I, 1);
4391+
break;
4392+
}
4393+
43224394
default:
43234395
if (!handleUnknownIntrinsic(I))
43244396
visitInstruction(I);

0 commit comments

Comments
 (0)