Skip to content

Commit 4a05a2c

Browse files
committed
[CHERIOT] Add a TTI callback to disallow LSR base register expressions.
This allows us to turn on SCEV for cheriot, with the caveat that we need to disallow LSR base register expressions that are negatively indexed, since they may not be representable on cheriot.
1 parent b9c085c commit 4a05a2c

File tree

12 files changed

+110
-56
lines changed

12 files changed

+110
-56
lines changed

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,8 @@ class TargetTransformInfo {
787787
AddressingModeKind getPreferredAddressingMode(const Loop *L,
788788
ScalarEvolution *SE) const;
789789

790+
bool isLegalBaseRegForLSR(const SCEV *) const;
791+
790792
/// Return true if the target supports masked store.
791793
bool isLegalMaskedStore(Type *DataType, Align Alignment) const;
792794
/// Return true if the target supports masked load.
@@ -1996,6 +1998,7 @@ class TargetTransformInfo::Concept {
19961998
TargetLibraryInfo *LibInfo) = 0;
19971999
virtual AddressingModeKind
19982000
getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const = 0;
2001+
virtual bool isLegalBaseRegForLSR(const SCEV *) const = 0;
19992002
virtual bool isLegalMaskedStore(Type *DataType, Align Alignment) = 0;
20002003
virtual bool isLegalMaskedLoad(Type *DataType, Align Alignment) = 0;
20012004
virtual bool isLegalNTStore(Type *DataType, Align Alignment) = 0;
@@ -2534,6 +2537,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
25342537
ScalarEvolution *SE) const override {
25352538
return Impl.getPreferredAddressingMode(L, SE);
25362539
}
2540+
bool isLegalBaseRegForLSR(const SCEV *S) const override {
2541+
return Impl.isLegalBaseRegForLSR(S);
2542+
}
25372543
bool isLegalMaskedStore(Type *DataType, Align Alignment) override {
25382544
return Impl.isLegalMaskedStore(DataType, Alignment);
25392545
}

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ class TargetTransformInfoImplBase {
276276
return TTI::AMK_None;
277277
}
278278

279+
bool isLegalBaseRegForLSR(const SCEV *S) const { return true; }
280+
279281
bool isLegalMaskedStore(Type *DataType, Align Alignment) const {
280282
return false;
281283
}

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6296,12 +6296,6 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
62966296
assert(GEP->getSourceElementType()->isSized() &&
62976297
"GEP source element type must be sized");
62986298

6299-
const DataLayout &DL = F.getParent()->getDataLayout();
6300-
// FIXME: Ideally, we should teach Scalar Evolution to
6301-
// understand fat pointers.
6302-
if (DL.isFatPointer(GEP->getPointerOperandType()->getPointerAddressSpace()))
6303-
return getUnknown(GEP);
6304-
63056299
SmallVector<const SCEV *, 4> IndexExprs;
63066300
for (Value *Index : GEP->indices())
63076301
IndexExprs.push_back(getSCEV(Index));

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,10 @@ TargetTransformInfo::getPreferredAddressingMode(const Loop *L,
463463
return TTIImpl->getPreferredAddressingMode(L, SE);
464464
}
465465

466+
bool TargetTransformInfo::isLegalBaseRegForLSR(const SCEV *S) const {
467+
return TTIImpl->isLegalBaseRegForLSR(S);
468+
}
469+
466470
bool TargetTransformInfo::isLegalMaskedStore(Type *DataType,
467471
Align Alignment) const {
468472
return TTIImpl->isLegalMaskedStore(DataType, Alignment);

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "RISCVTargetTransformInfo.h"
1010
#include "MCTargetDesc/RISCVMatInt.h"
1111
#include "llvm/ADT/STLExtras.h"
12+
#include "llvm/Analysis/ScalarEvolution.h"
1213
#include "llvm/Analysis/TargetTransformInfo.h"
1314
#include "llvm/CodeGen/BasicTTIImpl.h"
1415
#include "llvm/CodeGen/CostTable.h"
@@ -2401,6 +2402,26 @@ RISCVTTIImpl::getPreferredAddressingMode(const Loop *L,
24012402
return BasicTTIImplBase::getPreferredAddressingMode(L, SE);
24022403
}
24032404

2405+
bool RISCVTTIImpl::isLegalBaseRegForLSR(const SCEV *S) const {
2406+
if (ST->hasVendorXCheriot()) {
2407+
// Disallow any add-recurrence SCEV where the base offset is negative.
2408+
// This is needed because CHERIoT can't represent pointers before the
2409+
// beginning of an array.
2410+
if (const auto *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
2411+
const auto *StartAdd = dyn_cast<SCEVAddExpr>(AddRec->getStart());
2412+
if (StartAdd) {
2413+
const auto *Offset = dyn_cast<SCEVConstant>(StartAdd->getOperand(0));
2414+
if (Offset && Offset->getValue()->isNegative())
2415+
return false;
2416+
Offset = dyn_cast<SCEVConstant>(StartAdd->getOperand(1));
2417+
if (Offset && Offset->getValue()->isNegative())
2418+
return false;
2419+
}
2420+
}
2421+
}
2422+
return BasicTTIImplBase::isLegalBaseRegForLSR(S);
2423+
}
2424+
24042425
bool RISCVTTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
24052426
const TargetTransformInfo::LSRCost &C2) {
24062427
// RISC-V specific here are "instruction number 1st priority".

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
394394
TTI::AddressingModeKind getPreferredAddressingMode(const Loop *L,
395395
ScalarEvolution *SE) const;
396396

397+
bool isLegalBaseRegForLSR(const SCEV *S) const;
398+
397399
unsigned getRegisterClassForType(bool Vector, Type *Ty = nullptr) const {
398400
if (Vector)
399401
return RISCVRegisterClass::VRRC;

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,10 @@ void Cost::RateFormula(const Formula &F,
15161516
return;
15171517
}
15181518
for (const SCEV *BaseReg : F.BaseRegs) {
1519+
if (!TTI->isLegalBaseRegForLSR(BaseReg)) {
1520+
Lose();
1521+
return;
1522+
}
15191523
if (VisitedRegs.count(BaseReg)) {
15201524
Lose();
15211525
return;

llvm/test/CodeGen/RISCV/cheri/calling-conv-il32pc64.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ define i32 @get_ith_word(i32 signext %i, ...) addrspace(200) nounwind {
1313
; CHECK-NEXT: addi a0, a0, 1
1414
; CHECK-NEXT: .LBB0_1: # %while.cond
1515
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
16-
; CHECK-NEXT: cmove ca2, ca1
1716
; CHECK-NEXT: addi a0, a0, -1
1817
; CHECK-NEXT: cincoffset ca1, ca1, 4
1918
; CHECK-NEXT: bgtz a0, .LBB0_1
2019
; CHECK-NEXT: # %bb.2: # %while.end
2120
; CHECK-NEXT: csc ca1, 8(csp)
22-
; CHECK-NEXT: clw a0, 0(ca2)
21+
; CHECK-NEXT: clw a0, -4(ca1)
2322
; CHECK-NEXT: cincoffset csp, csp, 16
2423
; CHECK-NEXT: cret
2524
entry:

llvm/test/CodeGen/RISCV/cheri/calling-conv-l64pc128.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ define i32 @get_ith_word(i32 signext %i, ...) addrspace(200) nounwind {
1313
; CHECK-NEXT: addi a0, a0, 1
1414
; CHECK-NEXT: .LBB0_1: # %while.cond
1515
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
16-
; CHECK-NEXT: cmove ca2, ca1
1716
; CHECK-NEXT: addiw a0, a0, -1
1817
; CHECK-NEXT: cincoffset ca1, ca1, 4
1918
; CHECK-NEXT: bgtz a0, .LBB0_1
2019
; CHECK-NEXT: # %bb.2: # %while.end
2120
; CHECK-NEXT: csc ca1, 0(csp)
22-
; CHECK-NEXT: clw a0, 0(ca2)
21+
; CHECK-NEXT: clw a0, -4(ca1)
2322
; CHECK-NEXT: cincoffset csp, csp, 16
2423
; CHECK-NEXT: cret
2524
entry:

llvm/test/Transforms/LoopIdiom/cheri-preserve-tags-memcpy.ll

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --force-update
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
22
; Check that we retain the {must,no}_preserve_cheri_tags attribute when merging memcpy loops.
33
; FIXME: this does not work as expected with addrspace(200) pointers yet since we need SCEV.
44
; RUN: sed -e 's/-A200-P200-G200//g' -e 's/.p200/.p0/g' %s | \
@@ -32,25 +32,22 @@ define void @no_preserve(ptr addrspace("A") noalias writeonly %dst, ptr addrspac
3232
; HYBRID-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[COUNT]], 0
3333
; HYBRID-NEXT: br i1 [[CMP1]], label [[BB1_PREHEADER:%.*]], label [[BB2:%.*]]
3434
; HYBRID: bb1.preheader:
35-
; HYBRID-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 16
35+
; HYBRID-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 16
3636
; HYBRID-NEXT: [[TMP1:%.*]] = shl nuw i64 [[COUNT]], 4
37-
; HYBRID-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[DST]], ptr align 4 [[UGLYGEP]], i64 [[TMP1]], i1 false) #[[ATTR2:[0-9]+]]
37+
; HYBRID-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[DST]], ptr align 4 [[SCEVGEP]], i64 [[TMP1]], i1 false) #[[ATTR2:[0-9]+]]
3838
; HYBRID-NEXT: br label [[BB2]]
3939
; HYBRID: bb2:
4040
; HYBRID-NEXT: ret void
4141
;
4242
; PURECAP-LABEL: define {{[^@]+}}@no_preserve
4343
; PURECAP-SAME: (ptr addrspace(200) noalias writeonly [[DST:%.*]], ptr addrspace(200) noalias readonly [[SRC:%.*]], i64 [[COUNT:%.*]]) local_unnamed_addr addrspace(200) #[[ATTR0:[0-9]+]] {
4444
; PURECAP-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[COUNT]], 0
45-
; PURECAP-NEXT: br i1 [[CMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
46-
; PURECAP: bb1:
47-
; PURECAP-NEXT: [[IDX:%.*]] = phi i64 [ [[ADD:%.*]], [[BB1]] ], [ 0, [[TMP0:%.*]] ]
48-
; PURECAP-NEXT: [[LDST:%.*]] = getelementptr [[STRUCT_WOMBAT:%.*]], ptr addrspace(200) [[DST]], i64 [[IDX]]
49-
; PURECAP-NEXT: [[ADD]] = add nuw nsw i64 [[IDX]], 1
50-
; PURECAP-NEXT: [[LSRC:%.*]] = getelementptr [[STRUCT_WOMBAT]], ptr addrspace(200) [[SRC]], i64 [[ADD]]
51-
; PURECAP-NEXT: tail call void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) noundef nonnull align 16 dereferenceable(16) [[LDST]], ptr addrspace(200) noundef nonnull align 4 dereferenceable(16) [[LSRC]], i64 16, i1 false) #[[ATTR2:[0-9]+]]
52-
; PURECAP-NEXT: [[CMP2:%.*]] = icmp slt i64 [[ADD]], [[COUNT]]
53-
; PURECAP-NEXT: br i1 [[CMP2]], label [[BB1]], label [[BB2]]
45+
; PURECAP-NEXT: br i1 [[CMP1]], label [[BB1_PREHEADER:%.*]], label [[BB2:%.*]]
46+
; PURECAP: bb1.preheader:
47+
; PURECAP-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr addrspace(200) [[SRC]], i64 16
48+
; PURECAP-NEXT: [[TMP1:%.*]] = shl nuw i64 [[COUNT]], 4
49+
; PURECAP-NEXT: call void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) align 16 [[DST]], ptr addrspace(200) align 4 [[SCEVGEP]], i64 [[TMP1]], i1 false) #[[ATTR2:[0-9]+]]
50+
; PURECAP-NEXT: br label [[BB2]]
5451
; PURECAP: bb2:
5552
; PURECAP-NEXT: ret void
5653
;
@@ -82,25 +79,22 @@ define void @must_preserve(ptr addrspace("A") noalias writeonly %dst, ptr addrsp
8279
; HYBRID-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[COUNT]], 0
8380
; HYBRID-NEXT: br i1 [[CMP1]], label [[BB1_PREHEADER:%.*]], label [[BB2:%.*]]
8481
; HYBRID: bb1.preheader:
85-
; HYBRID-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 16
82+
; HYBRID-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 16
8683
; HYBRID-NEXT: [[TMP1:%.*]] = shl nuw i64 [[COUNT]], 4
87-
; HYBRID-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[DST]], ptr align 4 [[UGLYGEP]], i64 [[TMP1]], i1 false) #[[ATTR3:[0-9]+]]
84+
; HYBRID-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[DST]], ptr align 4 [[SCEVGEP]], i64 [[TMP1]], i1 false) #[[ATTR3:[0-9]+]]
8885
; HYBRID-NEXT: br label [[BB2]]
8986
; HYBRID: bb2:
9087
; HYBRID-NEXT: ret void
9188
;
9289
; PURECAP-LABEL: define {{[^@]+}}@must_preserve
9390
; PURECAP-SAME: (ptr addrspace(200) noalias writeonly [[DST:%.*]], ptr addrspace(200) noalias readonly [[SRC:%.*]], i64 [[COUNT:%.*]]) local_unnamed_addr addrspace(200) #[[ATTR0]] {
9491
; PURECAP-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[COUNT]], 0
95-
; PURECAP-NEXT: br i1 [[CMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
96-
; PURECAP: bb1:
97-
; PURECAP-NEXT: [[IDX:%.*]] = phi i64 [ [[ADD:%.*]], [[BB1]] ], [ 0, [[TMP0:%.*]] ]
98-
; PURECAP-NEXT: [[LDST:%.*]] = getelementptr [[STRUCT_WOMBAT:%.*]], ptr addrspace(200) [[DST]], i64 [[IDX]]
99-
; PURECAP-NEXT: [[ADD]] = add nuw nsw i64 [[IDX]], 1
100-
; PURECAP-NEXT: [[LSRC:%.*]] = getelementptr [[STRUCT_WOMBAT]], ptr addrspace(200) [[SRC]], i64 [[ADD]]
101-
; PURECAP-NEXT: tail call void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) noundef nonnull align 16 dereferenceable(16) [[LDST]], ptr addrspace(200) noundef nonnull align 4 dereferenceable(16) [[LSRC]], i64 16, i1 false) #[[ATTR3:[0-9]+]]
102-
; PURECAP-NEXT: [[CMP2:%.*]] = icmp slt i64 [[ADD]], [[COUNT]]
103-
; PURECAP-NEXT: br i1 [[CMP2]], label [[BB1]], label [[BB2]]
92+
; PURECAP-NEXT: br i1 [[CMP1]], label [[BB1_PREHEADER:%.*]], label [[BB2:%.*]]
93+
; PURECAP: bb1.preheader:
94+
; PURECAP-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr addrspace(200) [[SRC]], i64 16
95+
; PURECAP-NEXT: [[TMP1:%.*]] = shl nuw i64 [[COUNT]], 4
96+
; PURECAP-NEXT: call void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) align 16 [[DST]], ptr addrspace(200) align 4 [[SCEVGEP]], i64 [[TMP1]], i1 false) #[[ATTR3:[0-9]+]]
97+
; PURECAP-NEXT: br label [[BB2]]
10498
; PURECAP: bb2:
10599
; PURECAP-NEXT: ret void
106100
;
@@ -136,3 +130,5 @@ attributes #2 = { must_preserve_cheri_tags }
136130
; CHECK: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
137131
; CHECK: attributes #[[ATTR2]] = { no_preserve_cheri_tags }
138132
; CHECK: attributes #[[ATTR3]] = { must_preserve_cheri_tags }
133+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
134+
; CHECK: {{.*}}

0 commit comments

Comments
 (0)