Skip to content

Commit f8b7f64

Browse files
authored
[TTI][ASan][RISCV] Move InterestingMemoryOperand to Analysis and embed in MemIntrinsicInfo (#157863)
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 dd92609 commit f8b7f64

File tree

8 files changed

+2462
-38
lines changed

8 files changed

+2462
-38
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
55+
#endif // LLVM_ANALYSIS_INTERESTINGMEMORYOPERAND_H

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/ArrayRef.h"
2626
#include "llvm/ADT/BitmaskEnum.h"
2727
#include "llvm/Analysis/IVDescriptors.h"
28+
#include "llvm/Analysis/InterestingMemoryOperand.h"
2829
#include "llvm/IR/FMF.h"
2930
#include "llvm/IR/InstrTypes.h"
3031
#include "llvm/IR/PassManager.h"
@@ -88,6 +89,8 @@ struct MemIntrinsicInfo {
8889
bool WriteMem = false;
8990
bool IsVolatile = false;
9091

92+
SmallVector<InterestingMemoryOperand, 1> InterestingOperands;
93+
9194
bool isUnordered() const {
9295
return (Ordering == AtomicOrdering::NotAtomic ||
9396
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>
@@ -2701,6 +2702,82 @@ void RISCVTTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
27012702
BaseT::getPeelingPreferences(L, SE, PP);
27022703
}
27032704

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

163+
bool getTgtMemIntrinsic(IntrinsicInst *Inst,
164+
MemIntrinsicInfo &Info) const override;
165+
163166
unsigned getMinVectorRegisterBitWidth() const override {
164167
return ST->useRVVForFixedLengthVectors() ? 16 : 0;
165168
}

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 18 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,8 @@ 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,
849+
const TargetTransformInfo *TTI);
847850
bool maybeInsertAsanInitAtFunctionEntry(Function &F);
848851
bool maybeInsertDynamicShadowAtFunctionEntry(Function &F);
849852
void markEscapedLocalAllocas(Function &F);
@@ -1314,7 +1317,8 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
13141317
Options.MaxInlinePoisoningSize, Options.CompileKernel, Options.Recover,
13151318
Options.UseAfterScope, Options.UseAfterReturn);
13161319
const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
1317-
Modified |= FunctionSanitizer.instrumentFunction(F, &TLI);
1320+
const TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
1321+
Modified |= FunctionSanitizer.instrumentFunction(F, &TLI, &TTI);
13181322
}
13191323
Modified |= ModuleSanitizer.instrumentModule();
13201324
if (!Modified)
@@ -1452,7 +1456,8 @@ bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {
14521456
}
14531457

14541458
void AddressSanitizer::getInterestingMemoryOperands(
1455-
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) {
1459+
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
1460+
const TargetTransformInfo *TTI) {
14561461
// Do not instrument the load fetching the dynamic shadow address.
14571462
if (LocalDynamicShadow == I)
14581463
return;
@@ -1570,6 +1575,12 @@ void AddressSanitizer::getInterestingMemoryOperands(
15701575
break;
15711576
}
15721577
default:
1578+
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1579+
MemIntrinsicInfo IntrInfo;
1580+
if (TTI->getTgtMemIntrinsic(II, IntrInfo))
1581+
Interesting = IntrInfo.InterestingOperands;
1582+
return;
1583+
}
15731584
for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
15741585
if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) ||
15751586
ignoreAccess(I, CI->getArgOperand(ArgNo)))
@@ -2985,7 +2996,8 @@ bool AddressSanitizer::suppressInstrumentationSiteForDebug(int &Instrumented) {
29852996
}
29862997

29872998
bool AddressSanitizer::instrumentFunction(Function &F,
2988-
const TargetLibraryInfo *TLI) {
2999+
const TargetLibraryInfo *TLI,
3000+
const TargetTransformInfo *TTI) {
29893001
bool FunctionModified = false;
29903002

29913003
// Do not apply any instrumentation for naked functions.
@@ -3038,7 +3050,7 @@ bool AddressSanitizer::instrumentFunction(Function &F,
30383050
if (Inst.hasMetadata(LLVMContext::MD_nosanitize))
30393051
continue;
30403052
SmallVector<InterestingMemoryOperand, 1> InterestingOperands;
3041-
getInterestingMemoryOperands(&Inst, InterestingOperands);
3053+
getInterestingMemoryOperands(&Inst, InterestingOperands, TTI);
30423054

30433055
if (!InterestingOperands.empty()) {
30443056
for (auto &Operand : InterestingOperands) {

0 commit comments

Comments
 (0)