When adding noalias/alias.scope metadata, we analyze the instructions of the original callee, and then place metadata on the corresponding inlined instructions in the caller as provided by VMap. However, this assumes that this actually a clone of the instruction, rather than the result of simplification. If simplification occurred, the instruction that VMap points to may not have any relationship as far as ModRef behavior is concerned. Fix this by tracking simplified instructions during cloning and then only processing instructions that have not been simplified. This is done with an additional map form original to cloned instruction, into which we only insert if no simplification is performed. The mapping in VMap can then be compared to this map. If they're the same, the instruction hasn't been simplified. (I originally wanted to only track a set of simplified instructions, but that wouldn't work if the instruction only gets simplified afterwards, e.g. based on rewritten phis.) Fixes https://bugs.llvm.org/show_bug.cgi?id=50589. Differential Revision: https://reviews.llvm.org/D106242
57 lines
2.6 KiB
LLVM
57 lines
2.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -inline < %s | FileCheck %s
|
|
|
|
; Test interaction of simplification during cloning with insertion of scoped
|
|
; noalias metadata.
|
|
|
|
define <2 x i8> @callee1(<2 x i8>* %ptr1, <2 x i8>* noalias %ptr2, <2 x i1> %mask, <2 x i8> %passthru) {
|
|
; CHECK-LABEL: @callee1(
|
|
; CHECK-NEXT: [[RET:%.*]] = call <2 x i8> @llvm.masked.load.v2i8.p0v2i8(<2 x i8>* [[PTR1:%.*]], i32 1, <2 x i1> [[MASK:%.*]], <2 x i8> [[PASSTHRU:%.*]])
|
|
; CHECK-NEXT: store <2 x i8> zeroinitializer, <2 x i8>* [[PTR2:%.*]], align 2
|
|
; CHECK-NEXT: ret <2 x i8> [[RET]]
|
|
;
|
|
%ret = call <2 x i8> @llvm.masked.load.v2i8(<2 x i8>* %ptr1, i32 1, <2 x i1> %mask, <2 x i8> %passthru)
|
|
store <2 x i8> zeroinitializer, <2 x i8>* %ptr2
|
|
ret <2 x i8> %ret
|
|
}
|
|
|
|
; The load should not have !noalias.
|
|
define void @caller1(<2 x i8>* %ptr1, <2 x i8>* %ptr2) {
|
|
; CHECK-LABEL: @caller1(
|
|
; CHECK-NEXT: [[PASSTHRU:%.*]] = load <2 x i8>, <2 x i8>* [[PTR2:%.*]], align 2{{$}}
|
|
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
|
|
; CHECK-NEXT: store <2 x i8> zeroinitializer, <2 x i8>* [[PTR2]], align 2, !alias.scope !0
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%passthru = load <2 x i8>, <2 x i8>* %ptr2
|
|
call <2 x i8> @callee1(<2 x i8>* %ptr1, <2 x i8>* %ptr2, <2 x i1> zeroinitializer, <2 x i8> %passthru)
|
|
ret void
|
|
}
|
|
|
|
define <2 x i8> @callee2(<2 x i8>* %ptr1, <2 x i8>* noalias %ptr2, <2 x i1> %mask) {
|
|
; CHECK-LABEL: @callee2(
|
|
; CHECK-NEXT: [[PASSTHRU:%.*]] = load <2 x i8>, <2 x i8>* [[PTR2:%.*]], align 2
|
|
; CHECK-NEXT: [[RET:%.*]] = call <2 x i8> @llvm.masked.load.v2i8.p0v2i8(<2 x i8>* [[PTR1:%.*]], i32 1, <2 x i1> [[MASK:%.*]], <2 x i8> [[PASSTHRU]])
|
|
; CHECK-NEXT: store <2 x i8> zeroinitializer, <2 x i8>* [[PTR2]], align 2
|
|
; CHECK-NEXT: ret <2 x i8> [[RET]]
|
|
;
|
|
%passthru = load <2 x i8>, <2 x i8>* %ptr2
|
|
%ret = call <2 x i8> @llvm.masked.load.v2i8(<2 x i8>* %ptr1, i32 1, <2 x i1> %mask, <2 x i8> %passthru)
|
|
store <2 x i8> zeroinitializer, <2 x i8>* %ptr2
|
|
ret <2 x i8> %ret
|
|
}
|
|
|
|
; The load should not have !noalias.
|
|
define void @caller2(<2 x i8>* %ptr1, <2 x i8>* %ptr2) {
|
|
; CHECK-LABEL: @caller2(
|
|
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
|
|
; CHECK-NEXT: [[PASSTHRU_I:%.*]] = load <2 x i8>, <2 x i8>* [[PTR2:%.*]], align 2, !alias.scope !3{{$}}
|
|
; CHECK-NEXT: store <2 x i8> zeroinitializer, <2 x i8>* [[PTR2]], align 2, !alias.scope !3
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call <2 x i8> @callee2(<2 x i8>* %ptr1, <2 x i8>* %ptr2, <2 x i1> zeroinitializer)
|
|
ret void
|
|
}
|
|
|
|
declare <2 x i8> @llvm.masked.load.v2i8(<2 x i8>*, i32, <2 x i1>, <2 x i8>)
|