Skip to content

Commit c3c0b27

Browse files
authored
[Intrinsics] Add support for range attributes (#135642)
Add support for specifying range attributes in Intrinsics.td. Use this to specify the ucmp/scmp range [-1,2). This case is trickier than existing intrinsic attributes, because we need to create the attribute with the correct bitwidth. As such, the attribute construction now needs to be aware of the function type. We also need to be careful to no longer assign attributes on intrinsics with invalid signatures, as we'd make invalid assumptions about the number of arguments etc otherwise. Fixes #130179.
1 parent bd49bba commit c3c0b27

File tree

14 files changed

+90
-40
lines changed

14 files changed

+90
-40
lines changed

llvm/include/llvm/IR/Intrinsics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace Intrinsic {
8686
ID lookupIntrinsicID(StringRef Name);
8787

8888
/// Return the attributes for an intrinsic.
89-
AttributeList getAttributes(LLVMContext &C, ID id);
89+
AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT);
9090

9191
/// Return the function attributes for an intrinsic.
9292
AttributeSet getFnAttributes(LLVMContext &C, ID id);

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ class ReadNone<ArgIndex idx> : IntrinsicProperty {
134134
int ArgNo = idx.Value;
135135
}
136136

137+
// The return value or argument is in the range [lower, upper),
138+
// where lower and upper are interpreted as signed integers.
139+
class Range<AttrIndex idx, int lower, int upper> : IntrinsicProperty {
140+
int ArgNo = idx.Value;
141+
int Lower = lower;
142+
int Upper = upper;
143+
}
144+
137145
def IntrNoReturn : IntrinsicProperty;
138146

139147
// Applied by default.
@@ -1620,10 +1628,10 @@ def int_umin : DefaultAttrsIntrinsic<
16201628
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
16211629
def int_scmp : DefaultAttrsIntrinsic<
16221630
[llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>],
1623-
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
1631+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Range<RetIndex, -1, 2>]>;
16241632
def int_ucmp : DefaultAttrsIntrinsic<
16251633
[llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>],
1626-
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
1634+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Range<RetIndex, -1, 2>]>;
16271635

16281636
//===------------------------- Memory Use Markers -------------------------===//
16291637
//

llvm/lib/IR/AutoUpgrade.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,8 +1519,13 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
15191519
// Upgrade intrinsic attributes. This does not change the function.
15201520
if (NewFn)
15211521
F = NewFn;
1522-
if (Intrinsic::ID id = F->getIntrinsicID())
1523-
F->setAttributes(Intrinsic::getAttributes(F->getContext(), id));
1522+
if (Intrinsic::ID id = F->getIntrinsicID()) {
1523+
// Only do this if the intrinsic signature is valid.
1524+
SmallVector<Type *> OverloadTys;
1525+
if (Intrinsic::getIntrinsicSignature(id, F->getFunctionType(), OverloadTys))
1526+
F->setAttributes(
1527+
Intrinsic::getAttributes(F->getContext(), id, F->getFunctionType()));
1528+
}
15241529
return Upgraded;
15251530
}
15261531

llvm/lib/IR/Function.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,15 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace,
514514
// Ensure intrinsics have the right parameter attributes.
515515
// Note, the IntID field will have been set in Value::setName if this function
516516
// name is a valid intrinsic ID.
517-
if (IntID)
518-
setAttributes(Intrinsic::getAttributes(getContext(), IntID));
517+
if (IntID) {
518+
// Don't set the attributes if the intrinsic signature is invalid. This
519+
// case will either be auto-upgraded or fail verification.
520+
SmallVector<Type *> OverloadTys;
521+
if (!Intrinsic::getIntrinsicSignature(IntID, Ty, OverloadTys))
522+
return;
523+
524+
setAttributes(Intrinsic::getAttributes(getContext(), IntID, Ty));
525+
}
519526
}
520527

521528
Function::~Function() {

llvm/lib/IR/Intrinsics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/IR/Intrinsics.h"
1414
#include "llvm/ADT/StringExtras.h"
1515
#include "llvm/ADT/StringTable.h"
16+
#include "llvm/IR/ConstantRange.h"
1617
#include "llvm/IR/Function.h"
1718
#include "llvm/IR/IntrinsicsAArch64.h"
1819
#include "llvm/IR/IntrinsicsAMDGPU.h"

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16506,7 +16506,8 @@ Align SITargetLowering::computeKnownAlignForTargetInstr(
1650616506
// site specifies a lower alignment?
1650716507
Intrinsic::ID IID = GI->getIntrinsicID();
1650816508
LLVMContext &Ctx = VT.getMachineFunction().getFunction().getContext();
16509-
AttributeList Attrs = Intrinsic::getAttributes(Ctx, IID);
16509+
AttributeList Attrs =
16510+
Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
1651016511
if (MaybeAlign RetAlign = Attrs.getRetAlignment())
1651116512
return *RetAlign;
1651216513
}

llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2903,7 +2903,7 @@ static void stripNonValidAttributesFromPrototype(Function &F) {
29032903
// assumes that the attributes defined in Intrinsic.td are conservatively
29042904
// correct for both physical and abstract model.
29052905
if (Intrinsic::ID id = F.getIntrinsicID()) {
2906-
F.setAttributes(Intrinsic::getAttributes(Ctx, id));
2906+
F.setAttributes(Intrinsic::getAttributes(Ctx, id, F.getFunctionType()));
29072907
return;
29082908
}
29092909

llvm/test/Assembler/aarch64-intrinsics-attributes.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ declare i64 @llvm.aarch64.ldxr.p0(ptr)
1010
; CHECK: declare i32 @llvm.aarch64.stxp(i64, i64, ptr) [[NOFREE_NOUNWIND_WILLRETURN]]
1111
declare i32 @llvm.aarch64.stxp(i64, i64, ptr)
1212

13-
; CHECK: declare i32 @llvm.aarch64.dsb(i32) [[NOFREE_NOUNWIND_WILLRETURN]]
14-
declare i32 @llvm.aarch64.dsb(i32)
13+
; CHECK: declare void @llvm.aarch64.dsb(i32) [[NOFREE_NOUNWIND_WILLRETURN]]
14+
declare void @llvm.aarch64.dsb(i32)
1515

1616
; CHECK: declare i64 @llvm.aarch64.neon.sqdmulls.scalar(i32, i32) [[NO_CALLBACK_NOFREE_NOSYNC_NOUNWIND_READNONE_WILLRETURN:#[0-9]+]]
1717
declare i64 @llvm.aarch64.neon.sqdmulls.scalar(i32, i32)
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
1+
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
22

33
; Check that remangling code doesn't fail on an intrinsic with wrong signature
4+
; TODO: This should probably produce an error.
45

5-
; CHECK: Attribute after last parameter!
6-
; CHECK-NEXT: ptr @llvm.memset.i64
6+
; CHECK: declare void @llvm.memset.i64
77
declare void @llvm.memset.i64(ptr nocapture, i8, i64) nounwind
88

9-
; CHECK: Attribute after last parameter!
10-
; CHECK-NEXT: ptr @llvm.memcpy.i64
9+
; CHECK: declare void @llvm.memcpy.i64
1110
declare void @llvm.memcpy.i64(ptr nocapture, i8, i64) nounwind
1211

13-
; CHECK: Attribute after last parameter!
14-
; CHECK-NEXT: ptr @llvm.memmove.i64
12+
; CHECK: declare void @llvm.memmove.i64
1513
declare void @llvm.memmove.i64(ptr nocapture, i8, i64) nounwind

llvm/test/TableGen/intrinsic-attrs.td

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ def int_random_gen : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrHasSideEffec
66

77
def int_deref_ptr_ret : Intrinsic<[llvm_ptr_ty], [], [Dereferenceable<RetIndex, 16>]>;
88

9-
// CHECK: static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
10-
// CHECK-NEXT: switch (ID) {
9+
// CHECK: static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID,
10+
// CHECK-NEXT: Type *ArgType) {
11+
// CHECK-NEXT: unsigned BitWidth = ArgType->getScalarSizeInBits();
12+
// CHECK-NEXT: switch (ID) {
1113
// CHECK-NEXT: default: llvm_unreachable("Invalid attribute set number");
1214
// CHECK-NEXT: case 0:
1315
// CHECK-NEXT: return AttributeSet::get(C, {
@@ -26,13 +28,14 @@ def int_deref_ptr_ret : Intrinsic<[llvm_ptr_ty], [], [Dereferenceable<RetIndex,
2628
// CHECK: 0 << 8 | 0, // llvm.deref.ptr.ret
2729
// CHECK: 1 << 8 | 1, // llvm.random.gen
2830

29-
// CHECK: getAttributes(LLVMContext &C, ID id)
31+
// CHECK: getAttributes(LLVMContext &C, ID id,
32+
// CHECK-NEXT: FunctionType *FT) {
3033
// CHECK: case 1:
3134
// CHECK-NEXT: return AttributeList::get(C, {
3235
// CHECK-NEXT: {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, FnAttrID)}
3336
// CHECK-NEXT: });
3437
// CHECK-NEXT: case 0:
3538
// CHECK-NEXT: return AttributeList::get(C, {
36-
// CHECK-NEXT: {0, getIntrinsicArgAttributeSet(C, 0)},
39+
// CHECK-NEXT: {0, getIntrinsicArgAttributeSet(C, 0, FT->getContainedType(0))},
3740
// CHECK-NEXT: {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, FnAttrID)}
3841
// CHECK-NEXT: });

0 commit comments

Comments
 (0)