diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index 47e55017f1e2..310ac7b4d716 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -176,6 +176,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("target-flags", MIToken::kw_target_flags) .Case("volatile", MIToken::kw_volatile) .Case("non-temporal", MIToken::kw_non_temporal) + .Case("invariant", MIToken::kw_invariant) .Default(MIToken::Identifier); } diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 1ff7dda1151d..79bcb7fce01d 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -68,6 +68,7 @@ struct MIToken { kw_target_flags, kw_volatile, kw_non_temporal, + kw_invariant, // Identifier tokens Identifier, @@ -130,7 +131,8 @@ public: } bool isMemoryOperandFlag() const { - return Kind == kw_volatile || Kind == kw_non_temporal; + return Kind == kw_volatile || Kind == kw_non_temporal || + Kind == kw_invariant; } bool is(TokenKind K) const { return Kind == K; } diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 0c3f5ecce865..36460b3f3eb9 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1066,8 +1066,11 @@ bool MIParser::parseMemoryOperandFlag(unsigned &Flags) { case MIToken::kw_non_temporal: Flags |= MachineMemOperand::MONonTemporal; break; + case MIToken::kw_invariant: + Flags |= MachineMemOperand::MOInvariant; + break; // TODO: report an error when we specify the same flag more than once. - // TODO: parse the other memory operand flags. + // TODO: parse the target specific memory operand flags. default: llvm_unreachable("The current token should be a memory operand flag"); } diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index c84cec9ed2ec..cc131bc4641e 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -652,11 +652,13 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { void MIPrinter::print(const MachineMemOperand &Op) { OS << '('; - // TODO: Print operand's other flags. + // TODO: Print operand's target specific flags. if (Op.isVolatile()) OS << "volatile "; if (Op.isNonTemporal()) OS << "non-temporal "; + if (Op.isInvariant()) + OS << "invariant "; if (Op.isLoad()) OS << "load "; else { diff --git a/llvm/test/CodeGen/MIR/X86/memory-operands.mir b/llvm/test/CodeGen/MIR/X86/memory-operands.mir index 314cc1d28711..54e9cc47ba0e 100644 --- a/llvm/test/CodeGen/MIR/X86/memory-operands.mir +++ b/llvm/test/CodeGen/MIR/X86/memory-operands.mir @@ -35,6 +35,14 @@ !0 = !{i32 1} + define i32 @invariant_load(i32* %x) { + entry: + %v = load i32, i32* %x, !invariant.load !1 + ret i32 %v + } + + !1 = !{} + ... --- name: test @@ -100,3 +108,18 @@ body: - 'MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a)' - RETQ ... +--- +name: invariant_load +tracksRegLiveness: true +liveins: + - { reg: '%rdi' } +body: + - id: 0 + name: entry + liveins: [ '%rdi' ] + instructions: +# CHECK: name: invariant_load +# CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x) + - '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x)' + - 'RETQ %eax' +...