return SDValue();
}
-/// Canonicalize (LSUB p, 1) -> (LADD p, -1).
-static SDValue combineLockSub(SDNode *N, SelectionDAG &DAG,
- const X86Subtarget &Subtarget) {
- SDValue Chain = N->getOperand(0);
- SDValue LHS = N->getOperand(1);
- SDValue RHS = N->getOperand(2);
- MVT VT = RHS.getSimpleValueType();
- SDLoc DL(N);
-
- auto *C = dyn_cast<ConstantSDNode>(RHS);
- if (!C || C->getZExtValue() != 1)
- return SDValue();
-
- RHS = DAG.getConstant(-1, DL, VT);
- MachineMemOperand *MMO = cast<MemSDNode>(N)->getMemOperand();
- return DAG.getMemIntrinsicNode(X86ISD::LADD, DL,
- DAG.getVTList(MVT::i32, MVT::Other),
- {Chain, LHS, RHS}, VT, MMO);
-}
-
static SDValue combineTestM(SDNode *N, SelectionDAG &DAG,
const X86Subtarget &Subtarget) {
SDValue Op0 = N->getOperand(0);
case ISD::FMA: return combineFMA(N, DAG, Subtarget);
case ISD::MGATHER:
case ISD::MSCATTER: return combineGatherScatter(N, DAG);
- case X86ISD::LSUB: return combineLockSub(N, DAG, Subtarget);
case X86ISD::TESTM: return combineTestM(N, DAG, Subtarget);
case X86ISD::PCMPEQ:
case X86ISD::PCMPGT: return combineVectorCompare(N, DAG, Subtarget);
// ImmOpc8 corresponds to the mi8 version of the instruction
// ImmMod corresponds to the instruction format of the mi and mi8 versions
multiclass LOCK_ArithBinOp<bits<8> RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8,
- Format ImmMod, SDPatternOperator Op, string mnemonic> {
+ Format ImmMod, SDNode Op, string mnemonic> {
let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
SchedRW = [WriteALULd, WriteRMW] in {
defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">;
multiclass LOCK_ArithUnOp<bits<8> Opc8, bits<8> Opc, Format Form,
- int Increment, string mnemonic> {
+ SDNode Op, string mnemonic> {
let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
SchedRW = [WriteALULd, WriteRMW] in {
def NAME#8m : I<Opc8, Form, (outs), (ins i8mem :$dst),
!strconcat(mnemonic, "{b}\t$dst"),
- [(set EFLAGS, (X86lock_add addr:$dst, (i8 Increment)))],
+ [(set EFLAGS, (Op addr:$dst, (i8 1)))],
IIC_UNARY_MEM>, LOCK;
def NAME#16m : I<Opc, Form, (outs), (ins i16mem:$dst),
!strconcat(mnemonic, "{w}\t$dst"),
- [(set EFLAGS, (X86lock_add addr:$dst, (i16 Increment)))],
+ [(set EFLAGS, (Op addr:$dst, (i16 1)))],
IIC_UNARY_MEM>, OpSize16, LOCK;
def NAME#32m : I<Opc, Form, (outs), (ins i32mem:$dst),
!strconcat(mnemonic, "{l}\t$dst"),
- [(set EFLAGS, (X86lock_add addr:$dst, (i32 Increment)))],
+ [(set EFLAGS, (Op addr:$dst, (i32 1)))],
IIC_UNARY_MEM>, OpSize32, LOCK;
def NAME#64m : RI<Opc, Form, (outs), (ins i64mem:$dst),
!strconcat(mnemonic, "{q}\t$dst"),
- [(set EFLAGS, (X86lock_add addr:$dst, (i64 Increment)))],
+ [(set EFLAGS, (Op addr:$dst, (i64 1)))],
IIC_UNARY_MEM>, LOCK;
}
}
let Predicates = [UseIncDec] in {
-defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, 1, "inc">;
-defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, -1, "dec">;
+defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, X86lock_add, "inc">;
+defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, X86lock_sub, "dec">;
}
// Atomic compare and swap.
define i32 @test_sub_1_cmov_sle(i64* %p, i32 %a0, i32 %a1) #0 {
; CHECK-LABEL: test_sub_1_cmov_sle:
; CHECK: # BB#0: # %entry
-; CHECK-NEXT: lock decq (%rdi)
+; CHECK-NEXT: lock addq $-1, (%rdi)
; CHECK-NEXT: cmovgel %edx, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
define i32 @test_sub_1_cmov_sgt(i64* %p, i32 %a0, i32 %a1) #0 {
; CHECK-LABEL: test_sub_1_cmov_sgt:
; CHECK: # BB#0: # %entry
-; CHECK-NEXT: lock decq (%rdi)
+; CHECK-NEXT: lock addq $-1, (%rdi)
; CHECK-NEXT: cmovll %edx, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
define i8 @test_sub_1_setcc_sgt(i64* %p) #0 {
; CHECK-LABEL: test_sub_1_setcc_sgt:
; CHECK: # BB#0: # %entry
-; CHECK-NEXT: lock decq (%rdi)
+; CHECK-NEXT: lock addq $-1, (%rdi)
; CHECK-NEXT: setge %al
; CHECK-NEXT: retq
entry: