Skip to content

Commit 98d58c4

Browse files
committed
[TTI][ASan][RISCV] Move InterestingMemoryOperand to Analysis and embed in MemIntrinsicInfo
Previously asan considers target intrinsics as black boxes, so asan could not instrument accurate check. This patch make SmallVector<InterestingMemoryOperand> a member of MemIntrinsicInfo so that TTI can make targets describe their intrinsic informations to asan. Note, 1. This patch move InterestingMemoryOperand from Transforms to Analysis. 2. Extend MemIntrinsicInfo by adding a SmallVector<InterestingMemoryOperand> member. 3. This patch does not support RVV indexed/segment load/store.
1 parent 924bf24 commit 98d58c4

File tree

8 files changed

+2460
-38
lines changed

8 files changed

+2460
-38
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===- InterestingMemoryOperand.h -------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines InterestingMemoryOperand class that is used when getting
10+
// the information of a memory reference instruction.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_ANALYSIS_INTERESTINGMEMORYOPERAND_H
15+
#define LLVM_ANALYSIS_INTERESTINGMEMORYOPERAND_H
16+
17+
#include "llvm/IR/DataLayout.h"
18+
#include "llvm/IR/Instruction.h"
19+
#include "llvm/Support/TypeSize.h"
20+
21+
namespace llvm {
22+
class InterestingMemoryOperand {
23+
public:
24+
Use *PtrUse;
25+
bool IsWrite;
26+
Type *OpType;
27+
TypeSize TypeStoreSize = TypeSize::getFixed(0);
28+
MaybeAlign Alignment;
29+
// The mask Value, if we're looking at a masked load/store.
30+
Value *MaybeMask;
31+
// The EVL Value, if we're looking at a vp intrinsic.
32+
Value *MaybeEVL;
33+
// The Stride Value, if we're looking at a strided load/store.
34+
Value *MaybeStride;
35+
36+
InterestingMemoryOperand(Instruction *I, unsigned OperandNo, bool IsWrite,
37+
class Type *OpType, MaybeAlign Alignment,
38+
Value *MaybeMask = nullptr,
39+
Value *MaybeEVL = nullptr,
40+
Value *MaybeStride = nullptr)
41+
: IsWrite(IsWrite), OpType(OpType), Alignment(Alignment),
42+
MaybeMask(MaybeMask), MaybeEVL(MaybeEVL), MaybeStride(MaybeStride) {
43+
const DataLayout &DL = I->getDataLayout();
44+
TypeStoreSize = DL.getTypeStoreSizeInBits(OpType);
45+
PtrUse = &I->getOperandUse(OperandNo);
46+
}
47+
48+
Instruction *getInsn() { return cast<Instruction>(PtrUse->getUser()); }
49+
50+
Value *getPtr() { return PtrUse->get(); }
51+
};
52+
53+
} // namespace llvm
54+
#endif

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/APInt.h"
2525
#include "llvm/ADT/ArrayRef.h"
2626
#include "llvm/Analysis/IVDescriptors.h"
27+
#include "llvm/Analysis/InterestingMemoryOperand.h"
2728
#include "llvm/IR/FMF.h"
2829
#include "llvm/IR/InstrTypes.h"
2930
#include "llvm/IR/PassManager.h"
@@ -87,6 +88,8 @@ struct MemIntrinsicInfo {
8788
bool WriteMem = false;
8889
bool IsVolatile = false;
8990

91+
SmallVector<InterestingMemoryOperand, 1> Interesting;
92+
9093
bool isUnordered() const {
9194
return (Ordering == AtomicOrdering::NotAtomic ||
9295
Ordering == AtomicOrdering::Unordered) &&

llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,45 +14,14 @@
1414
#define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERCOMMON_H
1515

1616
#include "llvm/Analysis/CFG.h"
17+
#include "llvm/Analysis/InterestingMemoryOperand.h"
1718
#include "llvm/Analysis/PostDominators.h"
1819
#include "llvm/IR/Dominators.h"
1920
#include "llvm/IR/Instruction.h"
2021
#include "llvm/IR/IntrinsicInst.h"
2122
#include "llvm/IR/Module.h"
2223

2324
namespace llvm {
24-
25-
class InterestingMemoryOperand {
26-
public:
27-
Use *PtrUse;
28-
bool IsWrite;
29-
Type *OpType;
30-
TypeSize TypeStoreSize = TypeSize::getFixed(0);
31-
MaybeAlign Alignment;
32-
// The mask Value, if we're looking at a masked load/store.
33-
Value *MaybeMask;
34-
// The EVL Value, if we're looking at a vp intrinsic.
35-
Value *MaybeEVL;
36-
// The Stride Value, if we're looking at a strided load/store.
37-
Value *MaybeStride;
38-
39-
InterestingMemoryOperand(Instruction *I, unsigned OperandNo, bool IsWrite,
40-
class Type *OpType, MaybeAlign Alignment,
41-
Value *MaybeMask = nullptr,
42-
Value *MaybeEVL = nullptr,
43-
Value *MaybeStride = nullptr)
44-
: IsWrite(IsWrite), OpType(OpType), Alignment(Alignment),
45-
MaybeMask(MaybeMask), MaybeEVL(MaybeEVL), MaybeStride(MaybeStride) {
46-
const DataLayout &DL = I->getDataLayout();
47-
TypeStoreSize = DL.getTypeStoreSizeInBits(OpType);
48-
PtrUse = &I->getOperandUse(OperandNo);
49-
}
50-
51-
Instruction *getInsn() { return cast<Instruction>(PtrUse->getUser()); }
52-
53-
Value *getPtr() { return PtrUse->get(); }
54-
};
55-
5625
// Get AddressSanitizer parameters.
5726
void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize,
5827
bool IsKasan, uint64_t *ShadowBase,

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Analysis/TargetTransformInfo.h"
10+
#include "llvm/ADT/SmallVector.h"
1011
#include "llvm/Analysis/CFG.h"
1112
#include "llvm/Analysis/LoopIterator.h"
1213
#include "llvm/Analysis/TargetLibraryInfo.h"

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/CodeGen/TargetLowering.h"
1616
#include "llvm/CodeGen/ValueTypes.h"
1717
#include "llvm/IR/Instructions.h"
18+
#include "llvm/IR/IntrinsicsRISCV.h"
1819
#include "llvm/IR/PatternMatch.h"
1920
#include <cmath>
2021
#include <optional>
@@ -2703,6 +2704,82 @@ void RISCVTTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
27032704
BaseT::getPeelingPreferences(L, SE, PP);
27042705
}
27052706

2707+
bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
2708+
MemIntrinsicInfo &Info) const {
2709+
const DataLayout &DL = getDataLayout();
2710+
Intrinsic::ID IID = Inst->getIntrinsicID();
2711+
LLVMContext &C = Inst->getContext();
2712+
bool HasMask = false;
2713+
switch (IID) {
2714+
case Intrinsic::riscv_vle_mask:
2715+
case Intrinsic::riscv_vse_mask:
2716+
HasMask = true;
2717+
[[fallthrough]];
2718+
case Intrinsic::riscv_vle:
2719+
case Intrinsic::riscv_vse: {
2720+
// Intrinsic interface:
2721+
// riscv_vle(merge, ptr, vl)
2722+
// riscv_vle_mask(merge, ptr, mask, vl, policy)
2723+
// riscv_vse(val, ptr, vl)
2724+
// riscv_vse_mask(val, ptr, mask, vl, policy)
2725+
bool IsWrite = Inst->getType()->isVoidTy();
2726+
Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
2727+
const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
2728+
unsigned VLIndex = RVVIInfo->VLOperand;
2729+
unsigned PtrOperandNo = VLIndex - 1 - HasMask;
2730+
MaybeAlign Alignment =
2731+
Inst->getArgOperand(PtrOperandNo)->getPointerAlignment(DL);
2732+
Type *MaskType = Ty->getWithNewType(Type::getInt1Ty(C));
2733+
Value *Mask = ConstantInt::getTrue(MaskType);
2734+
if (HasMask)
2735+
Mask = Inst->getArgOperand(VLIndex - 1);
2736+
Value *EVL = Inst->getArgOperand(VLIndex);
2737+
Info.Interesting.emplace_back(Inst, PtrOperandNo, IsWrite, Ty, Alignment,
2738+
Mask, EVL);
2739+
return true;
2740+
}
2741+
case Intrinsic::riscv_vlse_mask:
2742+
case Intrinsic::riscv_vsse_mask:
2743+
HasMask = true;
2744+
[[fallthrough]];
2745+
case Intrinsic::riscv_vlse:
2746+
case Intrinsic::riscv_vsse: {
2747+
// Intrinsic interface:
2748+
// riscv_vlse(merge, ptr, stride, vl)
2749+
// riscv_vlse_mask(merge, ptr, stride, mask, vl, policy)
2750+
// riscv_vsse(val, ptr, stride, vl)
2751+
// riscv_vsse_mask(val, ptr, stride, mask, vl, policy)
2752+
bool IsWrite = Inst->getType()->isVoidTy();
2753+
Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
2754+
const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
2755+
unsigned VLIndex = RVVIInfo->VLOperand;
2756+
unsigned PtrOperandNo = VLIndex - 2 - HasMask;
2757+
MaybeAlign Alignment =
2758+
Inst->getArgOperand(PtrOperandNo)->getPointerAlignment(DL);
2759+
2760+
Value *Stride = Inst->getArgOperand(PtrOperandNo + 1);
2761+
// Use the pointer alignment as the element alignment if the stride is a
2762+
// multiple of the pointer alignment. Otherwise, the element alignment
2763+
// should be the greatest common divisor of pointer alignment and stride.
2764+
// For simplicity, just consider unalignment for elements.
2765+
unsigned PointerAlign = Alignment.valueOrOne().value();
2766+
if (!isa<ConstantInt>(Stride) ||
2767+
cast<ConstantInt>(Stride)->getZExtValue() % PointerAlign != 0)
2768+
Alignment = Align(1);
2769+
2770+
Type *MaskType = Ty->getWithNewType(Type::getInt1Ty(C));
2771+
Value *Mask = ConstantInt::getTrue(MaskType);
2772+
if (HasMask)
2773+
Mask = Inst->getArgOperand(VLIndex - 1);
2774+
Value *EVL = Inst->getArgOperand(VLIndex);
2775+
Info.Interesting.emplace_back(Inst, PtrOperandNo, IsWrite, Ty, Alignment,
2776+
Mask, EVL, Stride);
2777+
return true;
2778+
}
2779+
}
2780+
return false;
2781+
}
2782+
27062783
unsigned RISCVTTIImpl::getRegUsageForType(Type *Ty) const {
27072784
if (Ty->isVectorTy()) {
27082785
// f16 with only zvfhmin and bf16 will be promoted to f32

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ class RISCVTTIImpl final : public BasicTTIImplBase<RISCVTTIImpl> {
158158
void getPeelingPreferences(Loop *L, ScalarEvolution &SE,
159159
TTI::PeelingPreferences &PP) const override;
160160

161+
bool getTgtMemIntrinsic(IntrinsicInst *Inst,
162+
MemIntrinsicInfo &Info) const override;
163+
161164
unsigned getMinVectorRegisterBitWidth() const override {
162165
return ST->useRVVForFixedLengthVectors() ? 16 : 0;
163166
}

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/Analysis/MemoryBuiltins.h"
3030
#include "llvm/Analysis/StackSafetyAnalysis.h"
3131
#include "llvm/Analysis/TargetLibraryInfo.h"
32+
#include "llvm/Analysis/TargetTransformInfo.h"
3233
#include "llvm/Analysis/ValueTracking.h"
3334
#include "llvm/BinaryFormat/MachO.h"
3435
#include "llvm/Demangle/Demangle.h"
@@ -803,7 +804,8 @@ struct AddressSanitizer {
803804

804805
bool ignoreAccess(Instruction *Inst, Value *Ptr);
805806
void getInterestingMemoryOperands(
806-
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting);
807+
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
808+
const TargetTransformInfo *TTI);
807809

808810
void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
809811
InterestingMemoryOperand &O, bool UseCalls,
@@ -843,7 +845,7 @@ struct AddressSanitizer {
843845
void instrumentMemIntrinsic(MemIntrinsic *MI, RuntimeCallInserter &RTCI);
844846
Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
845847
bool suppressInstrumentationSiteForDebug(int &Instrumented);
846-
bool instrumentFunction(Function &F, const TargetLibraryInfo *TLI);
848+
bool instrumentFunction(Function &F, const TargetLibraryInfo *TLI, const TargetTransformInfo *TTI);
847849
bool maybeInsertAsanInitAtFunctionEntry(Function &F);
848850
bool maybeInsertDynamicShadowAtFunctionEntry(Function &F);
849851
void markEscapedLocalAllocas(Function &F);
@@ -1314,7 +1316,8 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
13141316
Options.MaxInlinePoisoningSize, Options.CompileKernel, Options.Recover,
13151317
Options.UseAfterScope, Options.UseAfterReturn);
13161318
const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
1317-
Modified |= FunctionSanitizer.instrumentFunction(F, &TLI);
1319+
const TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
1320+
Modified |= FunctionSanitizer.instrumentFunction(F, &TLI, &TTI);
13181321
}
13191322
Modified |= ModuleSanitizer.instrumentModule();
13201323
if (!Modified)
@@ -1452,7 +1455,8 @@ bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {
14521455
}
14531456

14541457
void AddressSanitizer::getInterestingMemoryOperands(
1455-
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) {
1458+
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
1459+
const TargetTransformInfo *TTI) {
14561460
// Do not instrument the load fetching the dynamic shadow address.
14571461
if (LocalDynamicShadow == I)
14581462
return;
@@ -1570,6 +1574,12 @@ void AddressSanitizer::getInterestingMemoryOperands(
15701574
break;
15711575
}
15721576
default:
1577+
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1578+
MemIntrinsicInfo IntrInfo;
1579+
if (TTI->getTgtMemIntrinsic(II, IntrInfo))
1580+
Interesting = IntrInfo.Interesting;
1581+
return;
1582+
}
15731583
for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
15741584
if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) ||
15751585
ignoreAccess(I, CI->getArgOperand(ArgNo)))
@@ -2985,7 +2995,8 @@ bool AddressSanitizer::suppressInstrumentationSiteForDebug(int &Instrumented) {
29852995
}
29862996

29872997
bool AddressSanitizer::instrumentFunction(Function &F,
2988-
const TargetLibraryInfo *TLI) {
2998+
const TargetLibraryInfo *TLI,
2999+
const TargetTransformInfo *TTI) {
29893000
bool FunctionModified = false;
29903001

29913002
// Do not apply any instrumentation for naked functions.
@@ -3038,7 +3049,7 @@ bool AddressSanitizer::instrumentFunction(Function &F,
30383049
if (Inst.hasMetadata(LLVMContext::MD_nosanitize))
30393050
continue;
30403051
SmallVector<InterestingMemoryOperand, 1> InterestingOperands;
3041-
getInterestingMemoryOperands(&Inst, InterestingOperands);
3052+
getInterestingMemoryOperands(&Inst, InterestingOperands, TTI);
30423053

30433054
if (!InterestingOperands.empty()) {
30443055
for (auto &Operand : InterestingOperands) {

0 commit comments

Comments
 (0)