Index: include/llvm/CodeGen/MachineInstr.h =================================================================== --- include/llvm/CodeGen/MachineInstr.h +++ include/llvm/CodeGen/MachineInstr.h @@ -80,7 +80,21 @@ FrameDestroy = 1 << 1, // Instruction is used as a part of // function frame destruction code. BundledPred = 1 << 2, // Instruction has bundled predecessors. - BundledSucc = 1 << 3 // Instruction has bundled successors. + BundledSucc = 1 << 3, // Instruction has bundled successors. + FmNoNans = 1 << 4, // Instruction does not support Fast + // math nan values. + FmNoInfs = 1 << 5, // Instruction does not support Fast + // math infinity values. + FmNsz = 1 << 6, // Instruction is not required to retain + // signed zero values. + FmArcp = 1 << 7, // Instruction supports Fast math + // reciprocal approximations. + FmContract = 1 << 8, // Instruction supports Fast math + // contraction operations like fma. + FmAfn = 1 << 9, // Instruction may map to Fast math + // instrinsic approximation. + FmReassoc = 1 << 10 // Instruction supports Fast math + // reassociation of operand order. }; private: @@ -93,7 +107,7 @@ using OperandCapacity = ArrayRecycler::Capacity; OperandCapacity CapOperands; // Capacity of the Operands array. - uint8_t Flags = 0; // Various bits of additional + uint16_t Flags = 0; // Various bits of additional // information about machine // instruction. @@ -186,7 +200,7 @@ /// Set a MI flag. void setFlag(MIFlag Flag) { - Flags |= (uint8_t)Flag; + Flags |= (uint16_t)Flag; } void setFlags(unsigned flags) { @@ -197,7 +211,7 @@ /// clearFlag - Clear a MI flag. void clearFlag(MIFlag Flag) { - Flags &= ~((uint8_t)Flag); + Flags &= ~((uint16_t)Flag); } /// Return true if MI is in a bundle (but not the first MI in a bundle). Index: lib/CodeGen/MIRParser/MILexer.h =================================================================== --- lib/CodeGen/MIRParser/MILexer.h +++ lib/CodeGen/MIRParser/MILexer.h @@ -64,6 +64,13 @@ kw_tied_def, kw_frame_setup, kw_frame_destroy, + kw_nnan, + kw_ninf, + kw_nsz, + kw_arcp, + kw_contract, + kw_afn, + kw_reassoc, kw_debug_location, kw_cfi_same_value, kw_cfi_offset, Index: lib/CodeGen/MIRParser/MILexer.cpp =================================================================== --- lib/CodeGen/MIRParser/MILexer.cpp +++ lib/CodeGen/MIRParser/MILexer.cpp @@ -212,6 +212,13 @@ .Case("tied-def", MIToken::kw_tied_def) .Case("frame-setup", MIToken::kw_frame_setup) .Case("frame-destroy", MIToken::kw_frame_destroy) + .Case("nnan", MIToken::kw_nnan) + .Case("ninf", MIToken::kw_ninf) + .Case("nsz", MIToken::kw_nsz) + .Case("arcp", MIToken::kw_arcp) + .Case("contract", MIToken::kw_contract) + .Case("afn", MIToken::kw_afn) + .Case("reassoc", MIToken::kw_reassoc) .Case("debug-location", MIToken::kw_debug_location) .Case("same_value", MIToken::kw_cfi_same_value) .Case("offset", MIToken::kw_cfi_offset) Index: lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIParser.cpp +++ lib/CodeGen/MIRParser/MIParser.cpp @@ -936,13 +936,36 @@ } bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { - // Allow both: - // * frame-setup frame-destroy OPCODE - // * frame-destroy frame-setup OPCODE + // Allow frame and fast math flags for OPCODE while (Token.is(MIToken::kw_frame_setup) || - Token.is(MIToken::kw_frame_destroy)) { - Flags |= Token.is(MIToken::kw_frame_setup) ? MachineInstr::FrameSetup - : MachineInstr::FrameDestroy; + Token.is(MIToken::kw_frame_destroy) || + Token.is(MIToken::kw_nnan) || + Token.is(MIToken::kw_ninf) || + Token.is(MIToken::kw_nsz) || + Token.is(MIToken::kw_arcp) || + Token.is(MIToken::kw_contract) || + Token.is(MIToken::kw_afn) || + Token.is(MIToken::kw_reassoc)) { + // Mine frame and fast math flags + if (Token.is(MIToken::kw_frame_setup)) + Flags |= MachineInstr::FrameSetup; + if (Token.is(MIToken::kw_frame_destroy)) + Flags |= MachineInstr::FrameDestroy; + if (Token.is(MIToken::kw_nnan)) + Flags |= MachineInstr::FmNoNans; + if (Token.is(MIToken::kw_ninf)) + Flags |= MachineInstr::FmNoInfs; + if (Token.is(MIToken::kw_nsz)) + Flags |= MachineInstr::FmNsz; + if (Token.is(MIToken::kw_arcp)) + Flags |= MachineInstr::FmArcp; + if (Token.is(MIToken::kw_contract)) + Flags |= MachineInstr::FmContract; + if (Token.is(MIToken::kw_afn)) + Flags |= MachineInstr::FmAfn; + if (Token.is(MIToken::kw_reassoc)) + Flags |= MachineInstr::FmReassoc; + lex(); } if (Token.isNot(MIToken::Identifier)) Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -672,6 +672,20 @@ OS << "frame-setup "; if (MI.getFlag(MachineInstr::FrameDestroy)) OS << "frame-destroy "; + if (MI.getFlag(MachineInstr::FmNoNans)) + OS << "nnan "; + if (MI.getFlag(MachineInstr::FmNoInfs)) + OS << "ninf "; + if (MI.getFlag(MachineInstr::FmNsz)) + OS << "nsz "; + if (MI.getFlag(MachineInstr::FmArcp)) + OS << "arcp "; + if (MI.getFlag(MachineInstr::FmContract)) + OS << "contract "; + if (MI.getFlag(MachineInstr::FmAfn)) + OS << "afn "; + if (MI.getFlag(MachineInstr::FmReassoc)) + OS << "reassoc "; OS << TII->getName(MI.getOpcode()); if (I < E) Index: lib/CodeGen/MachineInstr.cpp =================================================================== --- lib/CodeGen/MachineInstr.cpp +++ lib/CodeGen/MachineInstr.cpp @@ -1301,6 +1301,20 @@ OS << "frame-setup "; if (getFlag(MachineInstr::FrameDestroy)) OS << "frame-destroy "; + if (getFlag(MachineInstr::FmNoNans)) + OS << "nnan "; + if (getFlag(MachineInstr::FmNoInfs)) + OS << "ninf "; + if (getFlag(MachineInstr::FmNsz)) + OS << "nsz "; + if (getFlag(MachineInstr::FmArcp)) + OS << "arcp "; + if (getFlag(MachineInstr::FmContract)) + OS << "contract "; + if (getFlag(MachineInstr::FmAfn)) + OS << "afn "; + if (getFlag(MachineInstr::FmReassoc)) + OS << "reassoc "; // Print the opcode name. if (TII) Index: test/CodeGen/X86/sqrt-fastmath.mir =================================================================== --- test/CodeGen/X86/sqrt-fastmath.mir +++ test/CodeGen/X86/sqrt-fastmath.mir @@ -0,0 +1,103 @@ +# RUN: llc -march=x86-64 -run-pass none -o - %s | FileCheck %s +# This test ensures that the MIR parser parses the fast math instruction flags. + +--- | + + declare float @llvm.sqrt.f32(float) #0 + + define float @rfoo(float %f) #1 { + %sqrt = tail call float @llvm.sqrt.f32(float %f) + %div = fdiv fast float 1.000000e+00, %sqrt + ret float %div + } + +... +--- +name: rfoo +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +registers: + - { id: 0, class: fr32, preferred-register: '' } + - { id: 1, class: fr32, preferred-register: '' } + - { id: 2, class: fr32, preferred-register: '' } + - { id: 3, class: fr32, preferred-register: '' } + - { id: 4, class: fr32, preferred-register: '' } + - { id: 5, class: fr32, preferred-register: '' } + - { id: 6, class: fr32, preferred-register: '' } + - { id: 7, class: fr32, preferred-register: '' } + - { id: 8, class: fr32, preferred-register: '' } + - { id: 9, class: fr32, preferred-register: '' } + - { id: 10, class: fr32, preferred-register: '' } + - { id: 11, class: fr32, preferred-register: '' } + - { id: 12, class: fr32, preferred-register: '' } +liveins: + - { reg: '$xmm0', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: + - id: 0 + value: 'float -3.000000e+00' + alignment: 4 + isTargetSpecific: false + - id: 1 + value: float -5.000000e-01 + alignment: 4 + isTargetSpecific: false +body: | + bb.0 (%ir-block.0): + liveins: $xmm0 + + ; CHECK: %0:fr32 = COPY $xmm0 + %0:fr32 = COPY $xmm0 + %2:fr32 = IMPLICIT_DEF + ; CHECK: %1:fr32 = VRSQRTSSr killed %2, %0 + %1:fr32 = VRSQRTSSr killed %2, %0 + ; CHECK: %3:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %0, %1 + %3:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %0, %1 + ; CHECK: %4:fr32 = VMOVSSrm + %4:fr32 = VMOVSSrm $rip, 1, $noreg, %const.0, $noreg :: (load 4 from constant-pool) + ; CHECK: %5:fr32 = nnan ninf nsz arcp contract afn reassoc VFMADD213SSr %1, killed %3, %4 + %5:fr32 = nnan ninf nsz arcp contract afn reassoc VFMADD213SSr %1, killed %3, %4 + ; CHECK: %6:fr32 = VMOVSSrm + %6:fr32 = VMOVSSrm $rip, 1, $noreg, %const.1, $noreg :: (load 4 from constant-pool) + ; CHECK: %7:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %1, %6 + %7:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %1, %6 + ; CHECK: %8:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr killed %7, killed %5 + %8:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr killed %7, killed %5 + ; CHECK: %9:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %0, %8 + %9:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %0, %8 + ; CHECK: %10:fr32 = nnan ninf nsz arcp contract afn reassoc VFMADD213SSr %8, killed %9, %4 + %10:fr32 = nnan ninf nsz arcp contract afn reassoc VFMADD213SSr %8, killed %9, %4 + ; CHECK: %11:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %8, %6 + %11:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr %8, %6 + ; CHECK: %12:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr killed %11, killed %10 + %12:fr32 = nnan ninf nsz arcp contract afn reassoc VMULSSrr killed %11, killed %10 + ; CHECK: $xmm0 = COPY %12 + $xmm0 = COPY %12 + ; CHECK: RET 0, $xmm0 + RET 0, $xmm0 + +...