From: Alex Lorenz Date: Mon, 20 Jul 2015 20:51:18 +0000 (+0000) Subject: MIR Serialization: Initial serialization of machine constant pools. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0e4484f44d997b55636193629dde908e6b4510e6;p=oota-llvm.git MIR Serialization: Initial serialization of machine constant pools. This commit implements the initial serialization of machine constant pools and the constant pool index machine operands. The constant pool is serialized using a YAML sequence of YAML mappings that represent the constant values. The target-specific constant pool items aren't serialized by this commit. Reviewers: Duncan P. N. Exon Smith git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242707 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h index 41dde6cefa3..678cec9838a 100644 --- a/include/llvm/CodeGen/MIRYamlMapping.h +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -223,6 +223,20 @@ template <> struct MappingTraits { static const bool flow = true; }; +struct MachineConstantPoolValue { + unsigned ID; + StringValue Value; + unsigned Alignment = 0; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { + YamlIO.mapRequired("id", Constant.ID); + YamlIO.mapOptional("value", Constant.Value); + YamlIO.mapOptional("alignment", Constant.Alignment); + } +}; + struct MachineJumpTable { struct Entry { unsigned ID; @@ -247,6 +261,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) namespace llvm { @@ -320,6 +335,7 @@ struct MachineFunction { MachineFrameInfo FrameInfo; std::vector FixedStackObjects; std::vector StackObjects; + std::vector Constants; /// Constant pool. MachineJumpTable JumpTableInfo; std::vector BasicBlocks; @@ -338,6 +354,7 @@ template <> struct MappingTraits { YamlIO.mapOptional("frameInfo", MF.FrameInfo); YamlIO.mapOptional("fixedStack", MF.FixedStackObjects); YamlIO.mapOptional("stack", MF.StackObjects); + YamlIO.mapOptional("constants", MF.Constants); if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) YamlIO.mapOptional("jumpTable", MF.JumpTableInfo); YamlIO.mapOptional("body", MF.BasicBlocks); diff --git a/lib/CodeGen/MIRParser/MILexer.cpp b/lib/CodeGen/MIRParser/MILexer.cpp index 9ec12ee2427..ee4d59ddcaa 100644 --- a/lib/CodeGen/MIRParser/MILexer.cpp +++ b/lib/CodeGen/MIRParser/MILexer.cpp @@ -211,6 +211,10 @@ static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) { return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject); } +static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) { + return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem); +} + static Cursor lexVirtualRegister(Cursor C, MIToken &Token) { auto Range = C; C.advance(); // Skip '%' @@ -321,6 +325,8 @@ StringRef llvm::lexMIToken( return R.remaining(); if (Cursor R = maybeLexFixedStackObject(C, Token)) return R.remaining(); + if (Cursor R = maybeLexConstantPoolItem(C, Token)) + return R.remaining(); if (Cursor R = maybeLexRegister(C, Token)) return R.remaining(); if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback)) diff --git a/lib/CodeGen/MIRParser/MILexer.h b/lib/CodeGen/MIRParser/MILexer.h index 778640a2c81..fd94d61cab3 100644 --- a/lib/CodeGen/MIRParser/MILexer.h +++ b/lib/CodeGen/MIRParser/MILexer.h @@ -58,6 +58,7 @@ struct MIToken { // Other tokens IntegerLiteral, VirtualRegister, + ConstantPoolItem, JumpTableIndex }; @@ -122,7 +123,7 @@ public: return Kind == IntegerLiteral || Kind == MachineBasicBlock || Kind == StackObject || Kind == FixedStackObject || Kind == GlobalValue || Kind == VirtualRegister || - Kind == JumpTableIndex; + Kind == ConstantPoolItem || Kind == JumpTableIndex; } }; diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index b458a8b8882..34d3e1e3c53 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -108,6 +108,7 @@ public: bool parseStackObjectOperand(MachineOperand &Dest); bool parseFixedStackObjectOperand(MachineOperand &Dest); bool parseGlobalAddressOperand(MachineOperand &Dest); + bool parseConstantPoolIndexOperand(MachineOperand &Dest); bool parseJumpTableIndexOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest); @@ -531,6 +532,20 @@ bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) { return false; } +bool MIParser::parseConstantPoolIndexOperand(MachineOperand &Dest) { + assert(Token.is(MIToken::ConstantPoolItem)); + unsigned ID; + if (getUnsigned(ID)) + return true; + auto ConstantInfo = PFS.ConstantPoolSlots.find(ID); + if (ConstantInfo == PFS.ConstantPoolSlots.end()) + return error("use of undefined constant '%const." + Twine(ID) + "'"); + lex(); + // TODO: Parse offset and target flags. + Dest = MachineOperand::CreateCPI(ID, /*Offset=*/0); + return false; +} + bool MIParser::parseJumpTableIndexOperand(MachineOperand &Dest) { assert(Token.is(MIToken::JumpTableIndex)); unsigned ID; @@ -568,6 +583,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) { case MIToken::NamedGlobalValue: case MIToken::QuotedNamedGlobalValue: return parseGlobalAddressOperand(Dest); + case MIToken::ConstantPoolItem: + return parseConstantPoolIndexOperand(Dest); case MIToken::JumpTableIndex: return parseJumpTableIndexOperand(Dest); case MIToken::Error: diff --git a/lib/CodeGen/MIRParser/MIParser.h b/lib/CodeGen/MIRParser/MIParser.h index b34b7626eb8..888f2f57a31 100644 --- a/lib/CodeGen/MIRParser/MIParser.h +++ b/lib/CodeGen/MIRParser/MIParser.h @@ -31,6 +31,7 @@ struct PerFunctionMIParsingState { DenseMap VirtualRegisterSlots; DenseMap FixedStackObjectSlots; DenseMap StackObjectSlots; + DenseMap ConstantPoolSlots; DenseMap JumpTableSlots; }; diff --git a/lib/CodeGen/MIRParser/MIRParser.cpp b/lib/CodeGen/MIRParser/MIRParser.cpp index ca46de44740..a7c81ab390a 100644 --- a/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/lib/CodeGen/MIRParser/MIRParser.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/AsmParser/Parser.h" #include "llvm/AsmParser/SlotMapping.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -113,6 +114,11 @@ public: DenseMap &StackObjectSlots, DenseMap &FixedStackObjectSlots); + bool initializeConstantPool(MachineConstantPool &ConstantPool, + const yaml::MachineFunction &YamlMF, + const MachineFunction &MF, + DenseMap &ConstantPoolSlots); + bool initializeJumpTableInfo(MachineFunction &MF, const yaml::MachineJumpTable &YamlJTI, PerFunctionMIParsingState &PFS); @@ -273,6 +279,13 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { if (initializeFrameInfo(*MF.getFunction(), *MF.getFrameInfo(), YamlMF, PFS.StackObjectSlots, PFS.FixedStackObjectSlots)) return true; + if (!YamlMF.Constants.empty()) { + auto *ConstantPool = MF.getConstantPool(); + assert(ConstantPool && "Constant pool must be created"); + if (initializeConstantPool(*ConstantPool, YamlMF, MF, + PFS.ConstantPoolSlots)) + return true; + } const auto &F = *MF.getFunction(); for (const auto &YamlMBB : YamlMF.BasicBlocks) { @@ -439,6 +452,28 @@ bool MIRParserImpl::initializeFrameInfo( return false; } +bool MIRParserImpl::initializeConstantPool( + MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF, + const MachineFunction &MF, + DenseMap &ConstantPoolSlots) { + const auto &M = *MF.getFunction()->getParent(); + SMDiagnostic Error; + for (const auto &YamlConstant : YamlMF.Constants) { + const Constant *Value = dyn_cast_or_null( + parseConstantValue(YamlConstant.Value.Value, Error, M)); + if (!Value) + return error(Error, YamlConstant.Value.SourceRange); + unsigned Alignment = + YamlConstant.Alignment + ? YamlConstant.Alignment + : M.getDataLayout().getPrefTypeAlignment(Value->getType()); + // TODO: Report an error when the same constant pool value ID is redefined. + ConstantPoolSlots.insert(std::make_pair( + YamlConstant.ID, ConstantPool.getConstantPoolIndex(Value, Alignment))); + } + return false; +} + bool MIRParserImpl::initializeJumpTableInfo( MachineFunction &MF, const yaml::MachineJumpTable &YamlJTI, PerFunctionMIParsingState &PFS) { diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index a1c28bc5697..c3a655aec0b 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -14,6 +14,7 @@ #include "MIRPrinter.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -69,6 +70,8 @@ public: void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo, const TargetRegisterInfo *TRI); void convert(yaml::MachineFrameInfo &YamlMFI, const MachineFrameInfo &MFI); + void convert(yaml::MachineFunction &MF, + const MachineConstantPool &ConstantPool); void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI, const MachineJumpTableInfo &JTI); void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB, @@ -144,6 +147,8 @@ void MIRPrinter::print(const MachineFunction &MF) { convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); convert(YamlMF.FrameInfo, *MF.getFrameInfo()); convertStackObjects(YamlMF, *MF.getFrameInfo()); + if (const auto *ConstantPool = MF.getConstantPool()) + convert(YamlMF, *ConstantPool); ModuleSlotTracker MST(MF.getFunction()->getParent()); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) @@ -249,6 +254,25 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF, } } +void MIRPrinter::convert(yaml::MachineFunction &MF, + const MachineConstantPool &ConstantPool) { + unsigned ID = 0; + for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) { + // TODO: Serialize target specific constant pool entries. + if (Constant.isMachineConstantPoolEntry()) + llvm_unreachable("Can't print target specific constant pool entries yet"); + + yaml::MachineConstantPoolValue YamlConstant; + std::string Str; + raw_string_ostream StrOS(Str); + Constant.Val.ConstVal->printAsOperand(StrOS); + YamlConstant.ID = ID++; + YamlConstant.Value = StrOS.str(); + YamlConstant.Alignment = Constant.getAlignment(); + MF.Constants.push_back(YamlConstant); + } +} + void MIRPrinter::convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI, const MachineJumpTableInfo &JTI) { @@ -398,6 +422,10 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { case MachineOperand::MO_FrameIndex: printStackObjectReference(Op.getIndex()); break; + case MachineOperand::MO_ConstantPoolIndex: + OS << "%const." << Op.getIndex(); + // TODO: Print offset and target flags. + break; case MachineOperand::MO_JumpTableIndex: OS << "%jump-table." << Op.getIndex(); // TODO: Print target flags. diff --git a/test/CodeGen/MIR/X86/constant-pool.mir b/test/CodeGen/MIR/X86/constant-pool.mir new file mode 100644 index 00000000000..57508d1c51d --- /dev/null +++ b/test/CodeGen/MIR/X86/constant-pool.mir @@ -0,0 +1,118 @@ +# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the MIR parser parses constant pool constants and +# constant pool operands correctly. + +--- | + + define double @test(double %a, float %b) { + entry: + %c = fadd double %a, 3.250000e+00 + %d = fadd float %b, 6.250000e+00 + %e = fpext float %d to double + %f = fmul double %c, %e + ret double %f + } + + define double @test2(double %a, float %b) { + entry: + %c = fadd double %a, 3.250000e+00 + %d = fadd float %b, 6.250000e+00 + %e = fpext float %d to double + %f = fmul double %c, %e + ret double %f + } + + define double @test3(double %a, float %b) { + entry: + %c = fadd double %a, 3.250000e+00 + %d = fadd float %b, 6.250000e+00 + %e = fpext float %d to double + %f = fmul double %c, %e + ret double %f + } +... +--- +# CHECK: name: test +# CHECK: constants: +# CHECK-NEXT: - id: 0 +# CHECK-NEXT: value: 'double 3.250000e+00' +# CHECK-NEXT: alignment: 8 +# CHECK-NEXT: - id: 1 +# CHECK-NEXT: value: 'float 6.250000e+00' +# CHECK-NEXT: alignment: 4 +name: test +constants: + - id: 0 + value: 'double 3.250000e+00' + alignment: 8 + - id: 1 + value: 'float 6.250000e+00' + alignment: 4 +body: + - id: 0 + name: entry + instructions: + # CHECK: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ + # CHECK-NEXT: %xmm1 = ADDSSrm killed %xmm1, %rip, 1, _, %const.1, _ + - '%xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _' + - '%xmm1 = ADDSSrm killed %xmm1, %rip, 1, _, %const.1, _' + - '%xmm1 = CVTSS2SDrr killed %xmm1' + - '%xmm0 = MULSDrr killed %xmm0, killed %xmm1' + - 'RETQ %xmm0' +... +--- +# Verify that alignment can be inferred: +# CHECK: name: test2 +# CHECK: constants: +# CHECK-NEXT: - id: 0 +# CHECK-NEXT: value: 'double 3.250000e+00' +# CHECK-NEXT: alignment: 8 +# CHECK-NEXT: - id: 1 +# CHECK-NEXT: value: 'float 6.250000e+00' +# CHECK-NEXT: alignment: 4 +name: test2 +constants: + - id: 0 + value: 'double 3.250000e+00' + - id: 1 + value: 'float 6.250000e+00' +body: + - id: 0 + name: entry + instructions: + - '%xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _' + - '%xmm1 = ADDSSrm killed %xmm1, %rip, 1, _, %const.1, _' + - '%xmm1 = CVTSS2SDrr killed %xmm1' + - '%xmm0 = MULSDrr killed %xmm0, killed %xmm1' + - 'RETQ %xmm0' +... +--- +# Verify that the non-standard alignments are respected: +# CHECK: name: test3 +# CHECK: constants: +# CHECK-NEXT: - id: 0 +# CHECK-NEXT: value: 'double 3.250000e+00' +# CHECK-NEXT: alignment: 128 +# CHECK-NEXT: - id: 1 +# CHECK-NEXT: value: 'float 6.250000e+00' +# CHECK-NEXT: alignment: 1 +name: test3 +constants: + - id: 0 + value: 'double 3.250000e+00' + alignment: 128 + - id: 1 + value: 'float 6.250000e+00' + alignment: 1 +body: + - id: 0 + name: entry + instructions: + # CHECK: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ + # CHECK-NEXT: %xmm1 = ADDSSrm killed %xmm1, %rip, 1, _, %const.1, _ + - '%xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _' + - '%xmm1 = ADDSSrm killed %xmm1, %rip, 1, _, %const.1, _' + - '%xmm1 = CVTSS2SDrr killed %xmm1' + - '%xmm0 = MULSDrr killed %xmm0, killed %xmm1' + - 'RETQ %xmm0' +... diff --git a/test/CodeGen/MIR/X86/constant-value-error.mir b/test/CodeGen/MIR/X86/constant-value-error.mir new file mode 100644 index 00000000000..d6c21107022 --- /dev/null +++ b/test/CodeGen/MIR/X86/constant-value-error.mir @@ -0,0 +1,27 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that the MIR parser reports an error when parsing an invalid +# constant value. + +--- | + + define double @test(double %a, float %b) { + entry: + %c = fadd double %a, 3.250000e+00 + ret double %c + } + +... +--- +name: test +constants: + - id: 0 + # CHECK: [[@LINE+1]]:19: expected type + value: 'dub 3.250000e+00' +body: + - id: 0 + name: entry + instructions: + - '%xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _' + - 'RETQ %xmm0' +... + diff --git a/test/CodeGen/MIR/X86/invalid-constant-pool-item.mir b/test/CodeGen/MIR/X86/invalid-constant-pool-item.mir new file mode 100644 index 00000000000..de2ca4cca75 --- /dev/null +++ b/test/CodeGen/MIR/X86/invalid-constant-pool-item.mir @@ -0,0 +1,27 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that the MIR parser reports an error when parsing an invalid +# constant pool item operand. + +--- | + + define double @test(double %a, float %b) { + entry: + %c = fadd double %a, 3.250000e+00 + ret double %c + } + +... +--- +name: test +constants: + - id: 0 + value: 'double 3.250000e+00' +body: + - id: 0 + name: entry + instructions: + # CHECK: [[@LINE+1]]:52: use of undefined constant '%const.10' + - '%xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.10, _' + - 'RETQ %xmm0' +... +