Skip to content

Commit 1a56360

Browse files
authored
[IR] Treat calls with byval ptrs as read-only (#122961)
1 parent e19bc76 commit 1a56360

File tree

6 files changed

+27
-10
lines changed

6 files changed

+27
-10
lines changed

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,11 @@ class CallBase : public Instruction {
17191719
// FIXME: Once this API is no longer duplicated in `CallSite`, rename this to
17201720
// better indicate that this may return a conservative answer.
17211721
bool onlyReadsMemory(unsigned OpNo) const {
1722+
// If the argument is passed byval, the callee does not have access to the
1723+
// original pointer and thus cannot write to it.
1724+
if (OpNo < arg_size() && isByValArgument(OpNo))
1725+
return true;
1726+
17221727
return dataOperandHasImpliedAttr(OpNo, Attribute::ReadOnly) ||
17231728
dataOperandHasImpliedAttr(OpNo, Attribute::ReadNone);
17241729
}

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -890,14 +890,11 @@ determinePointerAccessAttrs(Argument *A,
890890
// can participate in the speculation.
891891
break;
892892

893-
const bool IsByVal =
894-
CB.isArgOperand(U) && CB.isByValArgument(CB.getArgOperandNo(U));
895-
896893
// The accessors used on call site here do the right thing for calls and
897894
// invokes with operand bundles.
898895
if (CB.doesNotAccessMemory(UseIndex)) {
899896
/* nop */
900-
} else if (!isModSet(ArgMR) || CB.onlyReadsMemory(UseIndex) || IsByVal) {
897+
} else if (!isModSet(ArgMR) || CB.onlyReadsMemory(UseIndex)) {
901898
IsRead = true;
902899
} else if (!isRefSet(ArgMR) ||
903900
CB.dataOperandHasImpliedAttr(UseIndex, Attribute::WriteOnly)) {

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,6 @@ isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V,
112112
if ((Call->onlyReadsMemory() && (Call->use_empty() || NoCapture)) ||
113113
(Call->onlyReadsMemory(DataOpNo) && NoCapture))
114114
continue;
115-
116-
// If this is being passed as a byval argument, the caller is making a
117-
// copy, so it is only a read of the alloca.
118-
if (IsArgOperand && Call->isByValArgument(DataOpNo))
119-
continue;
120115
}
121116

122117
// Lifetime intrinsics can be handled by the caller.

llvm/test/Analysis/BasicAA/call-attrs.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare void @readonly_attr(ptr readonly nocapture)
44
declare void @writeonly_attr(ptr writeonly nocapture)
55
declare void @readnone_attr(ptr readnone nocapture)
6+
declare void @byval_attr(ptr byval(i32))
67

78
declare void @readonly_func(ptr nocapture) readonly
89
declare void @writeonly_func(ptr nocapture) writeonly
@@ -24,6 +25,8 @@ entry:
2425
call void @readnone_attr(ptr %p)
2526
call void @readnone_func(ptr %p)
2627

28+
call void @byval_attr(ptr %p)
29+
2730
call void @read_write(ptr %p, ptr %p, ptr %p)
2831

2932
call void @func() ["deopt" (ptr %p)]
@@ -38,6 +41,7 @@ entry:
3841
; CHECK: Just Mod: Ptr: i8* %p <-> call void @writeonly_func(ptr %p)
3942
; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_attr(ptr %p)
4043
; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_func(ptr %p)
44+
; CHECK: Just Ref: Ptr: i8* %p <-> call void @byval_attr(ptr %p)
4145
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @read_write(ptr %p, ptr %p, ptr %p)
4246
; CHECK: Just Ref: Ptr: i8* %p <-> call void @func() [ "deopt"(ptr %p) ]
4347
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @writeonly_attr(ptr %p) [ "deopt"(ptr %p) ]

llvm/test/Analysis/BasicAA/tail-byval.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ entry:
1212
}
1313
; FIXME: This should be Just Ref.
1414
; CHECK-LABEL: Function: tailbyval: 1 pointers, 1 call sites
15-
; CHECK-NEXT: Both ModRef: Ptr: i32* %p <-> tail call void @takebyval(ptr byval(i32) %p)
15+
; CHECK-NEXT: Just Ref: Ptr: i32* %p <-> tail call void @takebyval(ptr byval(i32) %p)

llvm/test/Transforms/SROA/readonlynocapture.ll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,4 +390,20 @@ define i32 @testcallalloca() {
390390
ret i32 %l1
391391
}
392392

393+
declare void @callee_byval(ptr byval(i32) %p)
394+
395+
define i32 @simple_byval() {
396+
; CHECK-LABEL: @simple_byval(
397+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
398+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
399+
; CHECK-NEXT: call void @callee_byval(ptr [[A]])
400+
; CHECK-NEXT: ret i32 0
401+
;
402+
%a = alloca i32
403+
store i32 0, ptr %a
404+
call void @callee_byval(ptr %a)
405+
%l1 = load i32, ptr %a
406+
ret i32 %l1
407+
}
408+
393409
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)

0 commit comments

Comments
 (0)