1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[MIRParser] Add machine metadata.

- Add standalone metadata parsing support so that machine metadata nodes
  could be populated before and accessed during MIR is parsed.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D103282
This commit is contained in:
Michael Liao 2021-05-25 20:21:21 -04:00
parent b6f60388ba
commit 58a44149ab
20 changed files with 932 additions and 2 deletions

View File

@ -18,6 +18,8 @@
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/SMLoc.h"
#include <utility>
namespace llvm {
@ -164,6 +166,9 @@ struct PerFunctionMIParsingState {
const SlotMapping &IRSlots;
PerTargetMIParsingState &Target;
std::map<unsigned, TrackingMDNodeRef> MachineMetadataNodes;
std::map<unsigned, std::pair<TempMDTuple, SMLoc>> MachineForwardRefMDNodes;
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
DenseMap<Register, VRegInfo *> VRegInfos;
StringMap<VRegInfo *> VRegInfosNamed;
@ -233,6 +238,9 @@ bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI,
bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src,
SMDiagnostic &Error);
bool parseMachineMetadata(PerFunctionMIParsingState &PFS, StringRef Src,
SMRange SourceRange, SMDiagnostic &Error);
} // end namespace llvm
#endif // LLVM_CODEGEN_MIRPARSER_MIPARSER_H

View File

@ -273,6 +273,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case("bbsections", MIToken::kw_bbsections)
.Case("unknown-size", MIToken::kw_unknown_size)
.Case("unknown-address", MIToken::kw_unknown_address)
.Case("distinct", MIToken::kw_distinct)
.Default(MIToken::Identifier);
}

View File

@ -129,6 +129,9 @@ struct MIToken {
kw_unknown_size,
kw_unknown_address,
// Metadata types.
kw_distinct,
// Named metadata keywords
md_tbaa,
md_alias_scope,

View File

@ -395,6 +395,7 @@ class MIParser {
MachineFunction &MF;
SMDiagnostic &Error;
StringRef Source, CurrentSource;
SMRange SourceRange;
MIToken Token;
PerFunctionMIParsingState &PFS;
/// Maps from slot numbers to function's unnamed basic blocks.
@ -403,6 +404,8 @@ class MIParser {
public:
MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
StringRef Source);
MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
StringRef Source, SMRange SourceRange);
/// \p SkipChar gives the number of characters to skip before looking
/// for the next token.
@ -428,6 +431,10 @@ public:
bool parseStandaloneRegister(Register &Reg);
bool parseStandaloneStackObject(int &FI);
bool parseStandaloneMDNode(MDNode *&Node);
bool parseMachineMetadata();
bool parseMDTuple(MDNode *&MD, bool IsDistinct);
bool parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts);
bool parseMetadata(Metadata *&MD);
bool
parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);
@ -550,6 +557,10 @@ private:
/// parseStringConstant
/// ::= StringConstant
bool parseStringConstant(std::string &Result);
/// Map the location in the MI string to the corresponding location specified
/// in `SourceRange`.
SMLoc mapSMLoc(StringRef::iterator Loc);
};
} // end anonymous namespace
@ -559,6 +570,11 @@ MIParser::MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
: MF(PFS.MF), Error(Error), Source(Source), CurrentSource(Source), PFS(PFS)
{}
MIParser::MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
StringRef Source, SMRange SourceRange)
: MF(PFS.MF), Error(Error), Source(Source), CurrentSource(Source),
SourceRange(SourceRange), PFS(PFS) {}
void MIParser::lex(unsigned SkipChar) {
CurrentSource = lexMIToken(
CurrentSource.slice(SkipChar, StringRef::npos), Token,
@ -584,6 +600,13 @@ bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) {
return true;
}
SMLoc MIParser::mapSMLoc(StringRef::iterator Loc) {
assert(SourceRange.isValid() && "Invalid source range");
assert(Loc >= Source.data() && Loc <= (Source.data() + Source.size()));
return SMLoc::getFromPointer(SourceRange.Start.getPointer() +
(Loc - Source.data()));
}
typedef function_ref<bool(StringRef::iterator Loc, const Twine &)>
ErrorCallbackType;
@ -1172,6 +1195,130 @@ bool MIParser::parseStandaloneMDNode(MDNode *&Node) {
return false;
}
bool MIParser::parseMachineMetadata() {
lex();
if (Token.isNot(MIToken::exclaim))
return error("expected a metadata node");
lex();
if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isSigned())
return error("expected metadata id after '!'");
unsigned ID = 0;
if (getUnsigned(ID))
return true;
lex();
if (expectAndConsume(MIToken::equal))
return true;
bool IsDistinct = Token.is(MIToken::kw_distinct);
if (IsDistinct)
lex();
if (Token.isNot(MIToken::exclaim))
return error("expected a metadata node");
lex();
MDNode *MD;
if (parseMDTuple(MD, IsDistinct))
return true;
auto FI = PFS.MachineForwardRefMDNodes.find(ID);
if (FI != PFS.MachineForwardRefMDNodes.end()) {
FI->second.first->replaceAllUsesWith(MD);
PFS.MachineForwardRefMDNodes.erase(FI);
assert(PFS.MachineMetadataNodes[ID] == MD && "Tracking VH didn't work");
} else {
if (PFS.MachineMetadataNodes.count(ID))
return error("Metadata id is already used");
PFS.MachineMetadataNodes[ID].reset(MD);
}
return false;
}
bool MIParser::parseMDTuple(MDNode *&MD, bool IsDistinct) {
SmallVector<Metadata *, 16> Elts;
if (parseMDNodeVector(Elts))
return true;
MD = (IsDistinct ? MDTuple::getDistinct
: MDTuple::get)(MF.getFunction().getContext(), Elts);
return false;
}
bool MIParser::parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts) {
if (Token.isNot(MIToken::lbrace))
return error("expected '{' here");
lex();
if (Token.is(MIToken::rbrace)) {
lex();
return false;
}
do {
Metadata *MD;
if (parseMetadata(MD))
return true;
Elts.push_back(MD);
if (Token.isNot(MIToken::comma))
break;
lex();
} while (true);
if (Token.isNot(MIToken::rbrace))
return error("expected end of metadata node");
lex();
return false;
}
// ::= !42
// ::= !"string"
bool MIParser::parseMetadata(Metadata *&MD) {
if (Token.isNot(MIToken::exclaim))
return error("expected '!' here");
lex();
if (Token.is(MIToken::StringConstant)) {
std::string Str;
if (parseStringConstant(Str))
return true;
MD = MDString::get(MF.getFunction().getContext(), Str);
return false;
}
if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isSigned())
return error("expected metadata id after '!'");
SMLoc Loc = mapSMLoc(Token.location());
unsigned ID = 0;
if (getUnsigned(ID))
return true;
lex();
auto NodeInfo = PFS.IRSlots.MetadataNodes.find(ID);
if (NodeInfo != PFS.IRSlots.MetadataNodes.end()) {
MD = NodeInfo->second.get();
return false;
}
// Check machine metadata.
NodeInfo = PFS.MachineMetadataNodes.find(ID);
if (NodeInfo != PFS.MachineMetadataNodes.end()) {
MD = NodeInfo->second.get();
return false;
}
// Forward reference.
auto &FwdRef = PFS.MachineForwardRefMDNodes[ID];
FwdRef = std::make_pair(
MDTuple::getTemporary(MF.getFunction().getContext(), None), Loc);
PFS.MachineMetadataNodes[ID].reset(FwdRef.first.get());
MD = FwdRef.first.get();
return false;
}
static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
assert(MO.isImplicit());
return MO.isDef() ? "implicit-def" : "implicit";
@ -2014,8 +2161,11 @@ bool MIParser::parseMDNode(MDNode *&Node) {
if (getUnsigned(ID))
return true;
auto NodeInfo = PFS.IRSlots.MetadataNodes.find(ID);
if (NodeInfo == PFS.IRSlots.MetadataNodes.end())
return error(Loc, "use of undefined metadata '!" + Twine(ID) + "'");
if (NodeInfo == PFS.IRSlots.MetadataNodes.end()) {
NodeInfo = PFS.MachineMetadataNodes.find(ID);
if (NodeInfo == PFS.MachineMetadataNodes.end())
return error(Loc, "use of undefined metadata '!" + Twine(ID) + "'");
}
lex();
Node = NodeInfo->second.get();
return false;
@ -3281,6 +3431,11 @@ bool llvm::parseMDNode(PerFunctionMIParsingState &PFS,
return MIParser(PFS, Error, Src).parseStandaloneMDNode(Node);
}
bool llvm::parseMachineMetadata(PerFunctionMIParsingState &PFS, StringRef Src,
SMRange SrcRange, SMDiagnostic &Error) {
return MIParser(PFS, Error, Src, SrcRange).parseMachineMetadata();
}
bool MIRFormatter::parseIRValue(StringRef Src, MachineFunction &MF,
PerFunctionMIParsingState &PFS, const Value *&V,
ErrorCallbackType ErrorCallback) {

View File

@ -143,6 +143,10 @@ public:
bool initializeJumpTableInfo(PerFunctionMIParsingState &PFS,
const yaml::MachineJumpTable &YamlJTI);
bool parseMachineMetadataNodes(PerFunctionMIParsingState &PFS,
MachineFunction &MF,
const yaml::MachineFunction &YMF);
private:
bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
const yaml::StringValue &Source);
@ -151,6 +155,9 @@ private:
MachineBasicBlock *&MBB,
const yaml::StringValue &Source);
bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
const yaml::StringValue &Source);
/// Return a MIR diagnostic converted from an MI string diagnostic.
SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
SMRange SourceRange);
@ -457,6 +464,9 @@ MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
return true;
}
if (!YamlMF.MachineMetadataNodes.empty() &&
parseMachineMetadataNodes(PFS, MF, YamlMF))
return true;
StringRef BlockStr = YamlMF.Body.Value.Value;
SMDiagnostic Error;
@ -920,6 +930,29 @@ bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
return false;
}
bool MIRParserImpl::parseMachineMetadata(PerFunctionMIParsingState &PFS,
const yaml::StringValue &Source) {
SMDiagnostic Error;
if (llvm::parseMachineMetadata(PFS, Source.Value, Source.SourceRange, Error))
return error(Error, Source.SourceRange);
return false;
}
bool MIRParserImpl::parseMachineMetadataNodes(
PerFunctionMIParsingState &PFS, MachineFunction &MF,
const yaml::MachineFunction &YMF) {
for (auto &MDS : YMF.MachineMetadataNodes) {
if (parseMachineMetadata(PFS, MDS))
return true;
}
// Report missing definitions from forward referenced nodes.
if (!PFS.MachineForwardRefMDNodes.empty())
return error(PFS.MachineForwardRefMDNodes.begin()->second.second,
"use of undefined metadata '!" +
Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'");
return false;
}
SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
SMRange SourceRange) {
assert(SourceRange.isValid() && "Invalid source range");

View File

@ -0,0 +1,25 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
define i32 @test_memcpy(i32* nocapture %p, i32* nocapture readonly %q) {
ret i32 0
}
...
---
name: test_memcpy
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!10 = !{!9}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!5 = !{!6}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
body: |
bb.0 (%ir-block.0):
; CHECK: [[@LINE+1]]:78: use of undefined metadata '!11'
%2:fpr128 = LDRQui %0, 1 :: (load 16, align 4, !alias.scope !5, !noalias !11)
...

View File

@ -0,0 +1,166 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64-linux-gnu -run-pass=none -o - %s | FileCheck %s
--- |
; ModuleID = 'test/CodeGen/AArch64/memcpy-scoped-aa.ll'
source_filename = "test/CodeGen/AArch64/memcpy-scoped-aa.ll"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
define i32 @test_memcpy(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
define i32 @test_memcpy_inline(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
define i32 @test_mempcpy(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
%call = tail call i8* @mempcpy(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #0
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64 immarg, i1 immarg) #0
declare i8* @mempcpy(i8*, i8*, i64)
attributes #0 = { argmemonly nofree nounwind willreturn }
!0 = !{!1}
!1 = distinct !{!1, !2, !"bax: %p"}
!2 = distinct !{!2, !"bax"}
!3 = !{!4}
!4 = distinct !{!4, !2, !"bax: %q"}
...
---
name: test_memcpy
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!10 = !{!1, !9}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!5 = !{!1, !6}'
- '!11 = !{!4, !6}'
- '!8 = !{!4, !9}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
body: |
bb.0 (%ir-block.0):
liveins: $x0, $x1
; CHECK-LABEL: name: test_memcpy
; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x1
; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY $x0
; CHECK: [[LDRQui:%[0-9]+]]:fpr128 = LDRQui [[COPY1]], 1 :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
; CHECK: STRQui killed [[LDRQui]], [[COPY1]], 0 :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr killed [[LDRWui]], killed [[LDRWui1]]
; CHECK: $w0 = COPY [[ADDWrr]]
; CHECK: RET_ReallyLR implicit $w0
%1:gpr64common = COPY $x1
%0:gpr64common = COPY $x0
%2:fpr128 = LDRQui %0, 1 :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
STRQui killed %2, %0, 0 :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
%3:gpr32 = LDRWui %1, 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%4:gpr32 = LDRWui %1, 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
%5:gpr32 = ADDWrr killed %3, killed %4
$w0 = COPY %5
RET_ReallyLR implicit $w0
...
---
name: test_memcpy_inline
machineMetadataNodes:
- '!10 = !{!1, !9}'
- '!5 = !{!1, !6}'
- '!8 = !{!4, !9}'
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!11 = !{!4, !6}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!6 = distinct !{!6, !7, !"Src"}'
body: |
bb.0 (%ir-block.0):
liveins: $x0, $x1
; CHECK-LABEL: name: test_memcpy_inline
; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x1
; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY $x0
; CHECK: [[LDRQui:%[0-9]+]]:fpr128 = LDRQui [[COPY1]], 1 :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
; CHECK: STRQui killed [[LDRQui]], [[COPY1]], 0 :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr killed [[LDRWui]], killed [[LDRWui1]]
; CHECK: $w0 = COPY [[ADDWrr]]
; CHECK: RET_ReallyLR implicit $w0
%1:gpr64common = COPY $x1
%0:gpr64common = COPY $x0
%2:fpr128 = LDRQui %0, 1 :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
STRQui killed %2, %0, 0 :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
%3:gpr32 = LDRWui %1, 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%4:gpr32 = LDRWui %1, 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
%5:gpr32 = ADDWrr killed %3, killed %4
$w0 = COPY %5
RET_ReallyLR implicit $w0
...
---
name: test_mempcpy
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!8 = !{!4, !9}'
- '!5 = !{!1, !6}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!11 = !{!4, !6}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!10 = !{!1, !9}'
body: |
bb.0 (%ir-block.0):
liveins: $x0, $x1
; CHECK-LABEL: name: test_mempcpy
; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x1
; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY $x0
; CHECK: [[LDRQui:%[0-9]+]]:fpr128 = LDRQui [[COPY1]], 1 :: (load 16 from %ir.p1, align 1, !alias.scope !5, !noalias !8)
; CHECK: STRQui killed [[LDRQui]], [[COPY1]], 0 :: (store 16 into %ir.p0, align 1, !alias.scope !10, !noalias !11)
; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr killed [[LDRWui]], killed [[LDRWui1]]
; CHECK: $w0 = COPY [[ADDWrr]]
; CHECK: RET_ReallyLR implicit $w0
%1:gpr64common = COPY $x1
%0:gpr64common = COPY $x0
%2:fpr128 = LDRQui %0, 1 :: (load 16 from %ir.p1, align 1, !alias.scope !5, !noalias !8)
STRQui killed %2, %0, 0 :: (store 16 into %ir.p0, align 1, !alias.scope !10, !noalias !11)
%3:gpr32 = LDRWui %1, 0 :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%4:gpr32 = LDRWui %1, 1 :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
%5:gpr32 = ADDWrr killed %3, killed %4
$w0 = COPY %5
RET_ReallyLR implicit $w0
...

View File

@ -0,0 +1,25 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
target triple = "amdgcn-amd-amdhsa"
define i32 @test_memcpy(i32 addrspace(1)* nocapture %p, i32 addrspace(1)* nocapture readonly %q) #0 {
ret i32 0
}
...
---
name: test_memcpy
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!5 = !{!6}'
- '!10 = !{!9}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
body: |
bb.0 (%ir-block.0):
; CHECK: [[@LINE+1]]:113: use of undefined metadata '!11'
%8:vreg_128 = GLOBAL_LOAD_DWORDX4 %9, 16, 0, implicit $exec :: (load 16, align 4, !alias.scope !5, !noalias !11, addrspace 1)
...

View File

@ -0,0 +1,181 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -run-pass=none -o - %s | FileCheck %s
--- |
; ModuleID = 'test/CodeGen/AMDGPU/memcpy-scoped-aa.ll'
source_filename = "test/CodeGen/AMDGPU/memcpy-scoped-aa.ll"
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
target triple = "amdgcn-amd-amdhsa"
define i32 @test_memcpy(i32 addrspace(1)* nocapture %p, i32 addrspace(1)* nocapture readonly %q) #0 {
%p0 = bitcast i32 addrspace(1)* %p to i8 addrspace(1)*
%add.ptr = getelementptr inbounds i32, i32 addrspace(1)* %p, i64 4
%p1 = bitcast i32 addrspace(1)* %add.ptr to i8 addrspace(1)*
tail call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* noundef nonnull align 4 dereferenceable(16) %p0, i8 addrspace(1)* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%1 = bitcast i32 addrspace(1)* %q to <2 x i32> addrspace(1)*
%2 = load <2 x i32>, <2 x i32> addrspace(1)* %1, align 4, !alias.scope !3, !noalias !0
%v01 = extractelement <2 x i32> %2, i32 0
%v12 = extractelement <2 x i32> %2, i32 1
%add = add i32 %v01, %v12
ret i32 %add
}
define i32 @test_memcpy_inline(i32 addrspace(1)* nocapture %p, i32 addrspace(1)* nocapture readonly %q) #0 {
%p0 = bitcast i32 addrspace(1)* %p to i8 addrspace(1)*
%add.ptr = getelementptr inbounds i32, i32 addrspace(1)* %p, i64 4
%p1 = bitcast i32 addrspace(1)* %add.ptr to i8 addrspace(1)*
tail call void @llvm.memcpy.inline.p1i8.p1i8.i64(i8 addrspace(1)* noundef nonnull align 4 dereferenceable(16) %p0, i8 addrspace(1)* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%1 = bitcast i32 addrspace(1)* %q to <2 x i32> addrspace(1)*
%2 = load <2 x i32>, <2 x i32> addrspace(1)* %1, align 4, !alias.scope !3, !noalias !0
%v01 = extractelement <2 x i32> %2, i32 0
%v12 = extractelement <2 x i32> %2, i32 1
%add = add i32 %v01, %v12
ret i32 %add
}
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* noalias nocapture writeonly, i8 addrspace(1)* noalias nocapture readonly, i64, i1 immarg) #1
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.inline.p1i8.p1i8.i64(i8 addrspace(1)* noalias nocapture writeonly, i8 addrspace(1)* noalias nocapture readonly, i64 immarg, i1 immarg) #1
; Function Attrs: convergent nounwind willreturn
declare { i1, i32 } @llvm.amdgcn.if.i32(i1) #2
; Function Attrs: convergent nounwind willreturn
declare { i1, i32 } @llvm.amdgcn.else.i32.i32(i32) #2
; Function Attrs: convergent nounwind readnone willreturn
declare i32 @llvm.amdgcn.if.break.i32(i1, i32) #3
; Function Attrs: convergent nounwind willreturn
declare i1 @llvm.amdgcn.loop.i32(i32) #2
; Function Attrs: convergent nounwind willreturn
declare void @llvm.amdgcn.end.cf.i32(i32) #2
attributes #0 = { "target-cpu"="gfx1010" }
attributes #1 = { argmemonly nofree nounwind willreturn "target-cpu"="gfx1010" }
attributes #2 = { convergent nounwind willreturn }
attributes #3 = { convergent nounwind readnone willreturn }
!0 = !{!1}
!1 = distinct !{!1, !2, !"bax: %p"}
!2 = distinct !{!2, !"bax"}
!3 = !{!4}
!4 = distinct !{!4, !2, !"bax: %q"}
...
---
name: test_memcpy
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!11 = !{!4, !6}'
- '!5 = !{!1, !6}'
- '!8 = !{!4, !9}'
- '!10 = !{!1, !9}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
body: |
bb.0 (%ir-block.0):
liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $sgpr30_sgpr31
; CHECK-LABEL: name: test_memcpy
; CHECK: [[COPY:%[0-9]+]]:sreg_64 = COPY $sgpr30_sgpr31
; CHECK: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr3
; CHECK: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2
; CHECK: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr1
; CHECK: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0
; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load 8 from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
; CHECK: [[COPY10:%[0-9]+]]:ccr_sgpr_64 = COPY [[COPY]]
; CHECK: $vgpr0 = COPY [[V_ADD_U32_e64_]]
; CHECK: [[COPY11:%[0-9]+]]:ccr_sgpr_64 = COPY [[COPY10]]
; CHECK: S_SETPC_B64_return [[COPY11]], implicit $vgpr0
%4:sreg_64 = COPY $sgpr30_sgpr31
%3:vgpr_32 = COPY $vgpr3
%2:vgpr_32 = COPY $vgpr2
%1:vgpr_32 = COPY $vgpr1
%0:vgpr_32 = COPY $vgpr0
%17:vreg_64 = REG_SEQUENCE %2, %subreg.sub0, %3, %subreg.sub1
%18:vreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
%9:vreg_64 = COPY %18
%8:vreg_128 = GLOBAL_LOAD_DWORDX4 %9, 16, 0, implicit $exec :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
%10:vreg_64 = COPY %18
GLOBAL_STORE_DWORDX4 %10, killed %8, 0, 0, implicit $exec :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
%12:vreg_64 = COPY %17
%11:vreg_64 = GLOBAL_LOAD_DWORDX2 killed %12, 0, 0, implicit $exec :: (load 8 from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
%13:vgpr_32 = COPY %11.sub0
%14:vgpr_32 = COPY %11.sub1
%15:vgpr_32 = V_ADD_U32_e64 killed %13, killed %14, 0, implicit $exec
%5:ccr_sgpr_64 = COPY %4
$vgpr0 = COPY %15
%16:ccr_sgpr_64 = COPY %5
S_SETPC_B64_return %16, implicit $vgpr0
...
---
name: test_memcpy_inline
machineMetadataNodes:
- '!6 = distinct !{!6, !7, !"Src"}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!11 = !{!4, !6}'
- '!5 = !{!1, !6}'
- '!8 = !{!4, !9}'
- '!10 = !{!1, !9}'
body: |
bb.0 (%ir-block.0):
liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $sgpr30_sgpr31
; CHECK-LABEL: name: test_memcpy_inline
; CHECK: [[COPY:%[0-9]+]]:sreg_64 = COPY $sgpr30_sgpr31
; CHECK: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr3
; CHECK: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2
; CHECK: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr1
; CHECK: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0
; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load 8 from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
; CHECK: [[COPY10:%[0-9]+]]:ccr_sgpr_64 = COPY [[COPY]]
; CHECK: $vgpr0 = COPY [[V_ADD_U32_e64_]]
; CHECK: [[COPY11:%[0-9]+]]:ccr_sgpr_64 = COPY [[COPY10]]
; CHECK: S_SETPC_B64_return [[COPY11]], implicit $vgpr0
%4:sreg_64 = COPY $sgpr30_sgpr31
%3:vgpr_32 = COPY $vgpr3
%2:vgpr_32 = COPY $vgpr2
%1:vgpr_32 = COPY $vgpr1
%0:vgpr_32 = COPY $vgpr0
%17:vreg_64 = REG_SEQUENCE %2, %subreg.sub0, %3, %subreg.sub1
%18:vreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
%9:vreg_64 = COPY %18
%8:vreg_128 = GLOBAL_LOAD_DWORDX4 %9, 16, 0, implicit $exec :: (load 16 from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
%10:vreg_64 = COPY %18
GLOBAL_STORE_DWORDX4 %10, killed %8, 0, 0, implicit $exec :: (store 16 into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
%12:vreg_64 = COPY %17
%11:vreg_64 = GLOBAL_LOAD_DWORDX2 killed %12, 0, 0, implicit $exec :: (load 8 from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
%13:vgpr_32 = COPY %11.sub0
%14:vgpr_32 = COPY %11.sub1
%15:vgpr_32 = V_ADD_U32_e64 killed %13, killed %14, 0, implicit $exec
%5:ccr_sgpr_64 = COPY %4
$vgpr0 = COPY %15
%16:ccr_sgpr_64 = COPY %5
S_SETPC_B64_return %16, implicit $vgpr0
...

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '9 = distinct !{!9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:6: expected a metadata node

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '! = distinct !{!9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:8: expected metadata id after '!'

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct {!9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:20: expected a metadata node

View File

@ -0,0 +1,16 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!9 = distinct !{!9, !7, !"Src"}'
...
# CHECK: [[@LINE-2]]:37: Metadata id is already used

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !!9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:21: expected '{' here

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"'
...
# CHECK: [[@LINE-2]]:36: expected end of metadata node

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !{9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:22: expected '!' here

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !{!, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:23: expected metadata id after '!'

View File

@ -0,0 +1,15 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
define i32 @t0() {
ret i32 0
}
...
---
name: t0
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
...
# CHECK: [[@LINE-2]]:26: use of undefined metadata '!7'

View File

@ -0,0 +1,25 @@
# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser detects errors when parsing machine
# metadata.
--- |
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i32 @test_memcpy(i32* nocapture %p, i32* nocapture readonly %q) {
ret i32 0
}
...
---
name: test_memcpy
machineMetadataNodes:
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!5 = !{!6}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!10 = !{!9}'
body: |
bb.0 (%ir-block.0):
; CHECK: [[@LINE+1]]:96: use of undefined metadata '!11'
%2:gr64 = MOV64rm %0, 1, $noreg, 16, $noreg :: (load 8, align 4, !alias.scope !5, !noalias !11)
...

View File

@ -0,0 +1,172 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=none -o - %s | FileCheck %s
--- |
; ModuleID = 'test/CodeGen/X86/memcpy-scoped-aa.ll'
source_filename = "test/CodeGen/X86/memcpy-scoped-aa.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i32 @test_memcpy(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
define i32 @test_memcpy_inline(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16, i1 false), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
define i32 @test_mempcpy(i32* nocapture %p, i32* nocapture readonly %q) {
%p0 = bitcast i32* %p to i8*
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
%p1 = bitcast i32* %add.ptr to i8*
%call = tail call i8* @mempcpy(i8* noundef nonnull align 4 dereferenceable(16) %p0, i8* noundef nonnull align 4 dereferenceable(16) %p1, i64 16), !alias.scope !0, !noalias !3
%v0 = load i32, i32* %q, align 4, !alias.scope !3, !noalias !0
%q1 = getelementptr inbounds i32, i32* %q, i64 1
%v1 = load i32, i32* %q1, align 4, !alias.scope !3, !noalias !0
%add = add i32 %v0, %v1
ret i32 %add
}
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #0
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64 immarg, i1 immarg) #0
declare i8* @mempcpy(i8*, i8*, i64)
attributes #0 = { argmemonly nofree nounwind willreturn }
!0 = !{!1}
!1 = distinct !{!1, !2, !"bax: %p"}
!2 = distinct !{!2, !"bax"}
!3 = !{!4}
!4 = distinct !{!4, !2, !"bax: %q"}
...
---
name: test_memcpy
machineMetadataNodes:
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!8 = !{!4, !9}'
- '!5 = !{!1, !6}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!11 = !{!4, !6}'
- '!10 = !{!1, !9}'
body: |
bb.0 (%ir-block.0):
liveins: $rdi, $rsi
; CHECK-LABEL: name: test_memcpy
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store 8 into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store 8 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
%0:gr64 = COPY $rdi
%2:gr64 = MOV64rm %0, 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
%3:gr64 = MOV64rm %0, 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
MOV64mr %0, 1, $noreg, 8, $noreg, killed %3 :: (store 8 into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
MOV64mr %0, 1, $noreg, 0, $noreg, killed %2 :: (store 8 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
%4:gr32 = MOV32rm %1, 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%5:gr32 = ADD32rm %4, %1, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
$eax = COPY %5
RET 0, $eax
...
---
name: test_memcpy_inline
machineMetadataNodes:
- '!8 = !{!4, !9}'
- '!9 = distinct !{!9, !7, !"Dst"}'
- '!5 = !{!1, !6}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!11 = !{!4, !6}'
- '!10 = !{!1, !9}'
- '!6 = distinct !{!6, !7, !"Src"}'
body: |
bb.0 (%ir-block.0):
liveins: $rdi, $rsi
; CHECK-LABEL: name: test_memcpy_inline
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store 8 into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store 8 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
%0:gr64 = COPY $rdi
%2:gr64 = MOV64rm %0, 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 4, !alias.scope !5, !noalias !8)
%3:gr64 = MOV64rm %0, 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
MOV64mr %0, 1, $noreg, 8, $noreg, killed %3 :: (store 8 into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
MOV64mr %0, 1, $noreg, 0, $noreg, killed %2 :: (store 8 into %ir.p0, align 4, !alias.scope !10, !noalias !11)
%4:gr32 = MOV32rm %1, 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%5:gr32 = ADD32rm %4, %1, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
$eax = COPY %5
RET 0, $eax
...
---
name: test_mempcpy
machineMetadataNodes:
- '!5 = !{!1, !6}'
- '!8 = !{!4, !9}'
- '!11 = !{!4, !6}'
- '!10 = !{!1, !9}'
- '!7 = distinct !{!7, !"MemcpyLoweringDomain"}'
- '!6 = distinct !{!6, !7, !"Src"}'
- '!9 = distinct !{!9, !7, !"Dst"}'
body: |
bb.0 (%ir-block.0):
liveins: $rdi, $rsi
; CHECK-LABEL: name: test_mempcpy
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 1, !alias.scope !5, !noalias !8)
; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 1, !alias.scope !5, !noalias !8)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store 8 into %ir.p0 + 8, align 1, !alias.scope !10, !noalias !11)
; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store 8 into %ir.p0, align 1, !alias.scope !10, !noalias !11)
; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
%0:gr64 = COPY $rdi
%2:gr64 = MOV64rm %0, 1, $noreg, 16, $noreg :: (load 8 from %ir.p1, align 1, !alias.scope !5, !noalias !8)
%3:gr64 = MOV64rm %0, 1, $noreg, 24, $noreg :: (load 8 from %ir.p1 + 8, align 1, !alias.scope !5, !noalias !8)
MOV64mr %0, 1, $noreg, 8, $noreg, killed %3 :: (store 8 into %ir.p0 + 8, align 1, !alias.scope !10, !noalias !11)
MOV64mr %0, 1, $noreg, 0, $noreg, killed %2 :: (store 8 into %ir.p0, align 1, !alias.scope !10, !noalias !11)
%4:gr32 = MOV32rm %1, 1, $noreg, 0, $noreg :: (load 4 from %ir.q, !alias.scope !3, !noalias !0)
%5:gr32 = ADD32rm %4, %1, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %ir.q1, !alias.scope !3, !noalias !0)
$eax = COPY %5
RET 0, $eax
...