mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 05:18:46 +00:00
[SROA] Allow llvm.launder.invariant.group
intrinsic to be splittable
Let `llvm.launder.invariant.group` intrinsic as well as instructions operating on memory addresses, whose invariance may be broken by the intrinsic, to be rewritten. Fixes: https://github.com/llvm/llvm-project/issues/72035.
This commit is contained in:
parent
d3b75c4750
commit
ebbb9cdbb3
@ -1144,6 +1144,7 @@ private:
|
||||
}
|
||||
|
||||
if (II.isLaunderOrStripInvariantGroup()) {
|
||||
insertUse(II, Offset, AllocSize, true);
|
||||
enqueueUsers(II);
|
||||
return;
|
||||
}
|
||||
@ -3328,7 +3329,8 @@ private:
|
||||
}
|
||||
|
||||
bool visitIntrinsicInst(IntrinsicInst &II) {
|
||||
assert((II.isLifetimeStartOrEnd() || II.isDroppable()) &&
|
||||
assert((II.isLifetimeStartOrEnd() || II.isLaunderOrStripInvariantGroup() ||
|
||||
II.isDroppable()) &&
|
||||
"Unexpected intrinsic!");
|
||||
LLVM_DEBUG(dbgs() << " original: " << II << "\n");
|
||||
|
||||
@ -3342,6 +3344,9 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (II.isLaunderOrStripInvariantGroup())
|
||||
return true;
|
||||
|
||||
assert(II.getArgOperand(1) == OldPtr);
|
||||
// Lifetime intrinsics are only promotable if they cover the whole alloca.
|
||||
// Therefore, we drop lifetime intrinsics which don't cover the whole
|
||||
|
@ -44,9 +44,9 @@ define void @g() {
|
||||
; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
|
||||
; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue()
|
||||
; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue()
|
||||
; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group !0
|
||||
; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]]
|
||||
; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4
|
||||
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group !0
|
||||
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
|
||||
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4
|
||||
; CHECK-NEXT: call void @h(i32 [[V1]])
|
||||
; CHECK-NEXT: call void @h(i32 [[V2]])
|
||||
@ -79,6 +79,84 @@ define void @g() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @store_and_launder() {
|
||||
; CHECK-LABEL: @store_and_launder(
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%valptr = alloca i32, align 4
|
||||
store i32 0, ptr %valptr, align 4
|
||||
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @launder_and_load() {
|
||||
; CHECK-LABEL: @launder_and_load(
|
||||
; CHECK-NEXT: ret i32 undef
|
||||
;
|
||||
%valptr = alloca i32, align 4
|
||||
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
|
||||
%v2 = load i32, ptr %valptr
|
||||
ret i32 %v2
|
||||
}
|
||||
|
||||
define void @launder_and_ptr_arith() {
|
||||
; CHECK-LABEL: @launder_and_ptr_arith(
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%valptr = alloca i32, align 4
|
||||
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
|
||||
%a2 = getelementptr inbounds i32, ptr %valptr, i32 0
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @partial_use_of_alloca() {
|
||||
; CHECK-LABEL: @partial_use_of_alloca(
|
||||
; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store i32 0, ptr [[VALPTR]], align 4
|
||||
; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
|
||||
; CHECK-NEXT: [[LOAD_VAL:%.*]] = load i32, ptr [[VALPTR]], align 4
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[LOAD_VAL]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label [[USE_ALLOCA:%.*]], label [[END:%.*]]
|
||||
; CHECK: use_alloca:
|
||||
; CHECK-NEXT: call void @use(ptr nonnull [[VALPTR]])
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%valptr = alloca i32, align 4
|
||||
store i32 0, ptr %valptr, align 4
|
||||
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
|
||||
%load_val = load i32, ptr %valptr, align 4
|
||||
%cond = icmp eq i32 %load_val, 0
|
||||
br i1 %cond, label %use_alloca, label %end
|
||||
|
||||
use_alloca:
|
||||
call void @use(ptr nonnull %valptr)
|
||||
br label %end
|
||||
|
||||
end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @partial_promotion_of_alloca() {
|
||||
; CHECK-LABEL: @partial_promotion_of_alloca(
|
||||
; CHECK-NEXT: [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4
|
||||
; CHECK-NEXT: [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%struct_ptr = alloca %t, align 4
|
||||
%field_ptr = getelementptr inbounds %t, ptr %struct_ptr, i32 0, i32 0
|
||||
store i32 0, ptr %field_ptr, align 4
|
||||
%volatile_field_ptr = getelementptr inbounds %t, ptr %struct_ptr, i32 0, i32 1
|
||||
store volatile i32 0, ptr %volatile_field_ptr, align 4, !invariant.group !0
|
||||
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %struct_ptr)
|
||||
%load_val = load volatile i32, ptr %volatile_field_ptr, align 4, !invariant.group !0
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @use(i32*)
|
||||
|
||||
!0 = !{}
|
||||
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
|
||||
; CHECK-MODIFY-CFG: {{.*}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user