Index: lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h =================================================================== --- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h +++ lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h @@ -58,6 +58,10 @@ void initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI); + +/// Returns true if this instruction has a LOCK prefix. +bool hasLockPrefix(const MCInst &MI); + /// Create a X86 MCSubtargetInfo instance. This is exposed so Asm parser, etc. /// do not need to go through TargetRegistry. MCSubtargetInfo *createX86MCSubtargetInfo(const Triple &TT, StringRef CPU, Index: lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp =================================================================== --- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -70,6 +70,10 @@ return DWARFFlavour::X86_32_Generic; } +bool X86_MC::hasLockPrefix(const MCInst &MI) { + return MI.getFlags() & X86::IP_HAS_LOCK; +} + void X86_MC::initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI) { // FIXME: TableGen these. for (unsigned Reg = X86::NoRegister + 1; Reg < X86::NUM_TARGET_REGS; ++Reg) { Index: lib/Target/X86/X86InstrInfo.h =================================================================== --- lib/Target/X86/X86InstrInfo.h +++ lib/Target/X86/X86InstrInfo.h @@ -527,6 +527,10 @@ #define GET_INSTRINFO_HELPER_DECLS #include "X86GenInstrInfo.inc" + static bool hasLockPrefix(const MachineInstr &MI) { + return MI.getDesc().TSFlags & X86II::LOCK; + } + Optional describeLoadedValue(const MachineInstr &MI) const override; Index: lib/Target/X86/X86SchedPredicates.td =================================================================== --- lib/Target/X86/X86SchedPredicates.td +++ lib/Target/X86/X86SchedPredicates.td @@ -84,3 +84,48 @@ CheckImmOperand_s<5, "X86::COND_A">, CheckImmOperand_s<5, "X86::COND_BE"> ]>; + +// A predicate used to check if an instruction has a LOCK prefix. +def CheckLockPrefix : CheckFunctionPredicate< + "X86_MC::hasLockPrefix", + "X86InstrInfo::hasLockPrefix" +>; + +def IsRegRegCompareAndSwap_8 : CheckOpcode<[ CMPXCHG8rr ]>; + +def IsRegMemCompareAndSwap_8 : CheckOpcode<[ + LCMPXCHG8, CMPXCHG8rm +]>; + +def IsRegRegCompareAndSwap_16_32_64 : CheckOpcode<[ + CMPXCHG16rr, CMPXCHG32rr, CMPXCHG64rr +]>; + +def IsRegMemCompareAndSwap_16_32_64 : CheckOpcode<[ + CMPXCHG16rm, CMPXCHG32rm, CMPXCHG64rm, + CMPXCHG8B, CMPXCHG16B, + LCMPXCHG16, LCMPXCHG32, LCMPXCHG64, + LCMPXCHG8B, LCMPXCHG16B +]>; + +def IsRegMemCompareAndSwap : CheckOpcode< + !listconcat( + IsRegMemCompareAndSwap_8.ValidOpcodes, + IsRegMemCompareAndSwap_16_32_64.ValidOpcodes + )>; + +def IsRegRegCompareAndSwap : CheckOpcode< + !listconcat( + IsRegRegCompareAndSwap_8.ValidOpcodes, + IsRegRegCompareAndSwap_16_32_64.ValidOpcodes + )>; + +def IsAtomicCompareAndSwap_8 : CheckAll<[ + CheckLockPrefix, + IsRegMemCompareAndSwap_8 +]>; + +def IsAtomicCompareAndSwap : CheckAll<[ + CheckLockPrefix, + IsRegMemCompareAndSwap +]>; Index: lib/Target/X86/X86ScheduleBtVer2.td =================================================================== --- lib/Target/X86/X86ScheduleBtVer2.td +++ lib/Target/X86/X86ScheduleBtVer2.td @@ -191,10 +191,10 @@ defm : JWriteResIntPair; defm : JWriteResIntPair; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; -defm : X86WriteRes; +defm : X86WriteRes; +defm : X86WriteRes; +defm : X86WriteRes; +defm : X86WriteRes; defm : X86WriteRes; defm : JWriteResIntPair; @@ -305,6 +305,45 @@ // to '1' to tell the scheduler that the nop uses an ALU slot for a cycle. def : WriteRes { let Latency = 1; } +def JWriteCMPXCHG8rr : SchedWriteRes<[JALU01]> { + let Latency = 3; + let ResourceCycles = [3]; + let NumMicroOps = 3; +} + +def JWriteLOCK_CMPXCHG8rm : SchedWriteRes<[JALU01, JLAGU, JSAGU]> { + let Latency = 16; + let ResourceCycles = [3,16,16]; + let NumMicroOps = 5; +} + +def JWriteLOCK_CMPXCHGrm : SchedWriteRes<[JALU01, JLAGU, JSAGU]> { + let Latency = 17; + let ResourceCycles = [3,17,17]; + let NumMicroOps = 6; +} + +def JWriteCMPXCHG8rm : SchedWriteRes<[JALU01, JLAGU, JSAGU]> { + let Latency = 11; + let ResourceCycles = [3,1,1]; + let NumMicroOps = 5; +} + +def JWriteCMPXCHGVariant : SchedWriteVariant<[ + SchedVar, [JWriteLOCK_CMPXCHG8rm]>, + SchedVar, [JWriteLOCK_CMPXCHGrm]>, + SchedVar, [JWriteCMPXCHG8rm]>, + SchedVar, [WriteCMPXCHGRMW]>, + SchedVar, [JWriteCMPXCHG8rr]>, + SchedVar +]>; +def : InstRW<[JWriteCMPXCHGVariant], (instrs CMPXCHG8rr, LCMPXCHG8, CMPXCHG8rm, + CMPXCHG16rm, CMPXCHG32rm, CMPXCHG64rm, + LCMPXCHG16, LCMPXCHG32, LCMPXCHG64, + CMPXCHG8B, CMPXCHG16B, + LCMPXCHG8B, LCMPXCHG16B)>; + + //////////////////////////////////////////////////////////////////////////////// // Floating point. This covers both scalar and vector operations. //////////////////////////////////////////////////////////////////////////////// Index: test/tools/llvm-mca/X86/BtVer2/resources-cmpxchg.s =================================================================== --- test/tools/llvm-mca/X86/BtVer2/resources-cmpxchg.s +++ test/tools/llvm-mca/X86/BtVer2/resources-cmpxchg.s @@ -3,6 +3,23 @@ cmpxchg8b (%rax) cmpxchg16b (%rax) +lock cmpxchg8b (%rax) +lock cmpxchg16b (%rax) + +cmpxchgb %bl, %cl +cmpxchgw %bx, %cx +cmpxchgl %ebx, %ecx +cmpxchgq %rbx, %rcx + +cmpxchgb %bl, (%rsi) +cmpxchgw %bx, (%rsi) +cmpxchgl %ebx, (%rsi) +cmpxchgq %rbx, (%rsi) + +lock cmpxchgb %bl, (%rsi) +lock cmpxchgw %bx, (%rsi) +lock cmpxchgl %ebx, (%rsi) +lock cmpxchgq %rbx, (%rsi) # CHECK: Instruction Info: # CHECK-NEXT: [1]: #uOps @@ -13,8 +30,22 @@ # CHECK-NEXT: [6]: HasSideEffects (U) # CHECK: [1] [2] [3] [4] [5] [6] Instructions: -# CHECK-NEXT: 2 4 1.00 * * cmpxchg8b (%rax) -# CHECK-NEXT: 2 4 1.00 * * cmpxchg16b (%rax) +# CHECK-NEXT: 6 11 1.50 * * cmpxchg8b (%rax) +# CHECK-NEXT: 6 11 1.50 * * cmpxchg16b (%rax) +# CHECK-NEXT: 6 17 17.00 * * lock cmpxchg8b (%rax) +# CHECK-NEXT: 6 17 17.00 * * lock cmpxchg16b (%rax) +# CHECK-NEXT: 3 3 1.50 cmpxchgb %bl, %cl +# CHECK-NEXT: 5 3 1.50 cmpxchgw %bx, %cx +# CHECK-NEXT: 5 3 1.50 cmpxchgl %ebx, %ecx +# CHECK-NEXT: 5 3 1.50 cmpxchgq %rbx, %rcx +# CHECK-NEXT: 5 11 1.50 * * cmpxchgb %bl, (%rsi) +# CHECK-NEXT: 6 11 1.50 * * cmpxchgw %bx, (%rsi) +# CHECK-NEXT: 6 11 1.50 * * cmpxchgl %ebx, (%rsi) +# CHECK-NEXT: 6 11 1.50 * * cmpxchgq %rbx, (%rsi) +# CHECK-NEXT: 5 16 16.00 * * lock cmpxchgb %bl, (%rsi) +# CHECK-NEXT: 6 17 17.00 * * lock cmpxchgw %bx, (%rsi) +# CHECK-NEXT: 6 17 17.00 * * lock cmpxchgl %ebx, (%rsi) +# CHECK-NEXT: 6 17 17.00 * * lock cmpxchgq %rbx, (%rsi) # CHECK: Resources: # CHECK-NEXT: [0] - JALU0 @@ -34,9 +65,23 @@ # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] -# CHECK-NEXT: 1.00 1.00 - - - - - 2.00 - 2.00 - - - - +# CHECK-NEXT: 24.00 24.00 - - - - - 107.00 - 107.00 - - - - # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchg8b (%rax) -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchg16b (%rax) +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchg8b (%rax) +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchg16b (%rax) +# CHECK-NEXT: 1.50 1.50 - - - - - 17.00 - 17.00 - - - - lock cmpxchg8b (%rax) +# CHECK-NEXT: 1.50 1.50 - - - - - 17.00 - 17.00 - - - - lock cmpxchg16b (%rax) +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgb %bl, %cl +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgw %bx, %cx +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgl %ebx, %ecx +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgq %rbx, %rcx +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgb %bl, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgw %bx, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgl %ebx, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgq %rbx, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 16.00 - 16.00 - - - - lock cmpxchgb %bl, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 17.00 - 17.00 - - - - lock cmpxchgw %bx, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 17.00 - 17.00 - - - - lock cmpxchgl %ebx, (%rsi) +# CHECK-NEXT: 1.50 1.50 - - - - - 17.00 - 17.00 - - - - lock cmpxchgq %rbx, (%rsi) Index: test/tools/llvm-mca/X86/BtVer2/resources-x86_64.s =================================================================== --- test/tools/llvm-mca/X86/BtVer2/resources-x86_64.s +++ test/tools/llvm-mca/X86/BtVer2/resources-x86_64.s @@ -1106,14 +1106,14 @@ # CHECK-NEXT: 1 100 0.50 U cmpsw %es:(%rdi), (%rsi) # CHECK-NEXT: 1 100 0.50 U cmpsl %es:(%rdi), (%rsi) # CHECK-NEXT: 1 100 0.50 U cmpsq %es:(%rdi), (%rsi) -# CHECK-NEXT: 1 1 0.50 cmpxchgb %cl, %bl -# CHECK-NEXT: 2 4 1.00 * * cmpxchgb %cl, (%rbx) -# CHECK-NEXT: 1 1 0.50 cmpxchgw %cx, %bx -# CHECK-NEXT: 2 4 1.00 * * cmpxchgw %cx, (%rbx) -# CHECK-NEXT: 1 1 0.50 cmpxchgl %ecx, %ebx -# CHECK-NEXT: 2 4 1.00 * * cmpxchgl %ecx, (%rbx) -# CHECK-NEXT: 1 1 0.50 cmpxchgq %rcx, %rbx -# CHECK-NEXT: 2 4 1.00 * * cmpxchgq %rcx, (%rbx) +# CHECK-NEXT: 3 3 1.50 cmpxchgb %cl, %bl +# CHECK-NEXT: 5 11 1.50 * * cmpxchgb %cl, (%rbx) +# CHECK-NEXT: 5 3 1.50 cmpxchgw %cx, %bx +# CHECK-NEXT: 6 11 1.50 * * cmpxchgw %cx, (%rbx) +# CHECK-NEXT: 5 3 1.50 cmpxchgl %ecx, %ebx +# CHECK-NEXT: 6 11 1.50 * * cmpxchgl %ecx, (%rbx) +# CHECK-NEXT: 5 3 1.50 cmpxchgq %rcx, %rbx +# CHECK-NEXT: 6 11 1.50 * * cmpxchgq %rcx, (%rbx) # CHECK-NEXT: 1 100 0.50 U cpuid # CHECK-NEXT: 1 1 0.50 decb %dil # CHECK-NEXT: 1 5 1.00 * * decb (%rax) @@ -1697,7 +1697,7 @@ # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] -# CHECK-NEXT: 610.00 660.00 380.00 - - - - 330.00 64.00 231.00 - - - - +# CHECK-NEXT: 618.00 668.00 380.00 - - - - 330.00 64.00 231.00 - - - - # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: @@ -1908,14 +1908,14 @@ # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpsw %es:(%rdi), (%rsi) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpsl %es:(%rdi), (%rsi) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpsq %es:(%rdi), (%rsi) -# CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpxchgb %cl, %bl -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchgb %cl, (%rbx) -# CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpxchgw %cx, %bx -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchgw %cx, (%rbx) -# CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpxchgl %ecx, %ebx -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchgl %ecx, (%rbx) -# CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cmpxchgq %rcx, %rbx -# CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - cmpxchgq %rcx, (%rbx) +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgb %cl, %bl +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgb %cl, (%rbx) +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgw %cx, %bx +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgw %cx, (%rbx) +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgl %ecx, %ebx +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgl %ecx, (%rbx) +# CHECK-NEXT: 1.50 1.50 - - - - - - - - - - - - cmpxchgq %rcx, %rbx +# CHECK-NEXT: 1.50 1.50 - - - - - 1.00 - 1.00 - - - - cmpxchgq %rcx, (%rbx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - cpuid # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - decb %dil # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - 1.00 - - - - decb (%rax)