diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86InstrCompiler.td')
-rw-r--r-- | llvm/lib/Target/X86/X86InstrCompiler.td | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index 6ed62a00451..2c92cc370b5 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -737,6 +737,38 @@ defm LCMPXCHG8B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg8b", IIC_CMPX_LOCK_8B>; } +// This pseudo must be used when the frame uses RBX as +// the base pointer. Indeed, in such situation RBX is a reserved +// register and the register allocator will ignore any use/def of +// it. In other words, the register will not fix the clobbering of +// RBX that will happen when setting the arguments for the instrucion. +// +// Unlike the actual related instuction, we mark that this one +// defines EBX (instead of using EBX). +// The rationale is that we will define RBX during the expansion of +// the pseudo. The argument feeding EBX is ebx_input. +// +// The additional argument, $ebx_save, is a temporary register used to +// save the value of RBX accross the actual instruction. +// +// To make sure the register assigned to $ebx_save does not interfere with +// the definition of the actual instruction, we use a definition $dst which +// is tied to $rbx_save. That way, the live-range of $rbx_save spans accross +// the instruction and we are sure we will have a valid register to restore +// the value of RBX. +let Defs = [EAX, EDX, EBX, EFLAGS], Uses = [EAX, ECX, EDX], + SchedRW = [WriteALULd, WriteRMW], isCodeGenOnly = 1, isPseudo = 1, + Constraints = "$ebx_save = $dst", usesCustomInserter = 1 in { +def LCMPXCHG8B_SAVE_EBX : + I<0, Pseudo, (outs GR32:$dst), + (ins i64mem:$ptr, GR32:$ebx_input, GR32:$ebx_save), + !strconcat("cmpxchg8b", "\t$ptr"), + [(set GR32:$dst, (X86cas8save_ebx addr:$ptr, GR32:$ebx_input, + GR32:$ebx_save))], + IIC_CMPX_LOCK_8B>; +} + + let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX], Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW] in { defm LCMPXCHG16B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg16b", @@ -744,6 +776,20 @@ defm LCMPXCHG16B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg16b", IIC_CMPX_LOCK_16B>, REX_W; } +// Same as LCMPXCHG8B_SAVE_RBX but for the 16 Bytes variant. +let Defs = [RAX, RDX, RBX, EFLAGS], Uses = [RAX, RCX, RDX], + Predicates = [HasCmpxchg16b], SchedRW = [WriteALULd, WriteRMW], + isCodeGenOnly = 1, isPseudo = 1, Constraints = "$rbx_save = $dst", + usesCustomInserter = 1 in { +def LCMPXCHG16B_SAVE_RBX : + I<0, Pseudo, (outs GR64:$dst), + (ins i128mem:$ptr, GR64:$rbx_input, GR64:$rbx_save), + !strconcat("cmpxchg16b", "\t$ptr"), + [(set GR64:$dst, (X86cas16save_rbx addr:$ptr, GR64:$rbx_input, + GR64:$rbx_save))], + IIC_CMPX_LOCK_16B>; +} + defm LCMPXCHG : LCMPXCHG_BinOp<0xB0, 0xB1, MRMDestMem, "cmpxchg", X86cas, IIC_CMPX_LOCK_8, IIC_CMPX_LOCK>; |