mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-24 09:29:42 +00:00
Revert "X86: elide comparisons after cmpxchg instructions."
This reverts commit r210523. It was committed prematurely without waiting for review. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210524 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
984ee65445
commit
efbf7d1ceb
@ -3504,24 +3504,6 @@ static bool isX86CCUnsigned(unsigned X86CC) {
|
||||
llvm_unreachable("covered switch fell through?!");
|
||||
}
|
||||
|
||||
/// Convert an integer condition code to an x86 one in the most straightforward
|
||||
/// way possible, with no optimisation attempt.
|
||||
static unsigned getSimpleX86IntCC(ISD::CondCode SetCCOpcode) {
|
||||
switch (SetCCOpcode) {
|
||||
default: llvm_unreachable("Invalid integer condition!");
|
||||
case ISD::SETEQ: return X86::COND_E;
|
||||
case ISD::SETGT: return X86::COND_G;
|
||||
case ISD::SETGE: return X86::COND_GE;
|
||||
case ISD::SETLT: return X86::COND_L;
|
||||
case ISD::SETLE: return X86::COND_LE;
|
||||
case ISD::SETNE: return X86::COND_NE;
|
||||
case ISD::SETULT: return X86::COND_B;
|
||||
case ISD::SETUGT: return X86::COND_A;
|
||||
case ISD::SETULE: return X86::COND_BE;
|
||||
case ISD::SETUGE: return X86::COND_AE;
|
||||
}
|
||||
}
|
||||
|
||||
/// TranslateX86CC - do a one to one translation of a ISD::CondCode to the X86
|
||||
/// specific condition code, returning the condition code and the LHS/RHS of the
|
||||
/// comparison to make.
|
||||
@ -3545,7 +3527,19 @@ static unsigned TranslateX86CC(ISD::CondCode SetCCOpcode, bool isFP,
|
||||
}
|
||||
}
|
||||
|
||||
return getSimpleX86IntCC(SetCCOpcode);
|
||||
switch (SetCCOpcode) {
|
||||
default: llvm_unreachable("Invalid integer condition!");
|
||||
case ISD::SETEQ: return X86::COND_E;
|
||||
case ISD::SETGT: return X86::COND_G;
|
||||
case ISD::SETGE: return X86::COND_GE;
|
||||
case ISD::SETLT: return X86::COND_L;
|
||||
case ISD::SETLE: return X86::COND_LE;
|
||||
case ISD::SETNE: return X86::COND_NE;
|
||||
case ISD::SETULT: return X86::COND_B;
|
||||
case ISD::SETUGT: return X86::COND_A;
|
||||
case ISD::SETULE: return X86::COND_BE;
|
||||
case ISD::SETUGE: return X86::COND_AE;
|
||||
}
|
||||
}
|
||||
|
||||
// First determine if it is required or is profitable to flip the operands.
|
||||
@ -10380,77 +10374,10 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, SDLoc dl,
|
||||
return SDValue(New.getNode(), 1);
|
||||
}
|
||||
|
||||
static SDValue LowerCMP_SWAP(SDValue Op, const X86Subtarget *Subtarget,
|
||||
SelectionDAG &DAG) {
|
||||
MVT T = Op.getSimpleValueType();
|
||||
SDLoc DL(Op);
|
||||
unsigned Reg = 0;
|
||||
unsigned size = 0;
|
||||
switch(T.SimpleTy) {
|
||||
default: llvm_unreachable("Invalid value type!");
|
||||
case MVT::i8: Reg = X86::AL; size = 1; break;
|
||||
case MVT::i16: Reg = X86::AX; size = 2; break;
|
||||
case MVT::i32: Reg = X86::EAX; size = 4; break;
|
||||
case MVT::i64:
|
||||
assert(Subtarget->is64Bit() && "Node not type legal!");
|
||||
Reg = X86::RAX; size = 8;
|
||||
break;
|
||||
}
|
||||
SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), DL, Reg,
|
||||
Op.getOperand(2), SDValue());
|
||||
SDValue Ops[] = { cpIn.getValue(0),
|
||||
Op.getOperand(1),
|
||||
Op.getOperand(3),
|
||||
DAG.getTargetConstant(size, MVT::i8),
|
||||
cpIn.getValue(1) };
|
||||
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||
MachineMemOperand *MMO = cast<AtomicSDNode>(Op)->getMemOperand();
|
||||
SDValue Result = DAG.getMemIntrinsicNode(X86ISD::LCMPXCHG_DAG, DL, Tys,
|
||||
Ops, T, MMO);
|
||||
SDValue cpOut =
|
||||
DAG.getCopyFromReg(Result.getValue(0), DL, Reg, T, Result.getValue(1));
|
||||
return cpOut;
|
||||
}
|
||||
|
||||
|
||||
/// Emit nodes that will be selected as "cmp Op0,Op1", or something equivalent
|
||||
/// and set X86CC to the needed condition code to make use of the
|
||||
/// comparison. This may not be the obvious equivalent to CC if the comparison
|
||||
/// can be achieved more efficiently using a different method.
|
||||
SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, ISD::CondCode CC,
|
||||
SDLoc dl, SelectionDAG &DAG,
|
||||
unsigned &X86CC) const {
|
||||
// A cmpxchg instruction will actually perform the comparison
|
||||
if ((Op0.getOpcode() == ISD::ATOMIC_CMP_SWAP && Op0.getOperand(2) == Op1) ||
|
||||
(Op1.getOpcode() == ISD::ATOMIC_CMP_SWAP && Op1.getOperand(2) == Op0)) {
|
||||
SDValue CmpSwap;
|
||||
if (Op0.getOpcode() == ISD::ATOMIC_CMP_SWAP) {
|
||||
// x86's cmpxchg instruction performs the equivalent of "cmp desired,
|
||||
// loaded".
|
||||
CmpSwap = Op0;
|
||||
CC = getSetCCSwappedOperands(CC);
|
||||
} else
|
||||
CmpSwap = Op1;
|
||||
|
||||
// Lowering the CmpSwap node gives us a getCopyFromReg SDValue representing
|
||||
// the value loaded. I.e. the ATOMIC_CMP_SWAP
|
||||
X86CC = getSimpleX86IntCC(CC);
|
||||
SDValue EFLAGS = LowerCMP_SWAP(CmpSwap, Subtarget, DAG);
|
||||
DAG.ReplaceAllUsesOfValueWith(CmpSwap.getValue(0), EFLAGS);
|
||||
|
||||
// Glue on a copy from EFLAGS to be used in place of the required Cmp.
|
||||
EFLAGS = DAG.getCopyFromReg(EFLAGS.getValue(1), dl, X86::EFLAGS,
|
||||
MVT::i32, EFLAGS.getValue(2));
|
||||
DAG.ReplaceAllUsesOfValueWith(CmpSwap.getValue(1), EFLAGS.getValue(1));
|
||||
|
||||
return EFLAGS;
|
||||
}
|
||||
|
||||
bool IsFP = Op1.getSimpleValueType().isFloatingPoint();
|
||||
X86CC = TranslateX86CC(CC, IsFP, Op0, Op1, DAG);
|
||||
if (X86CC == X86::COND_INVALID)
|
||||
return SDValue();
|
||||
|
||||
/// Emit nodes that will be selected as "cmp Op0,Op1", or something
|
||||
/// equivalent.
|
||||
SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC,
|
||||
SDLoc dl, SelectionDAG &DAG) const {
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op1)) {
|
||||
if (C->getAPIntValue() == 0)
|
||||
return EmitTest(Op0, X86CC, dl, DAG);
|
||||
@ -10458,7 +10385,7 @@ SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, ISD::CondCode CC,
|
||||
if (Op0.getValueType() == MVT::i1)
|
||||
llvm_unreachable("Unexpected comparison operation for MVT::i1 operands");
|
||||
}
|
||||
|
||||
|
||||
if ((Op0.getValueType() == MVT::i8 || Op0.getValueType() == MVT::i16 ||
|
||||
Op0.getValueType() == MVT::i32 || Op0.getValueType() == MVT::i64)) {
|
||||
// Do the comparison at i32 if it's smaller, besides the Atom case.
|
||||
@ -11024,11 +10951,12 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
|
||||
return DAG.getSetCC(dl, VT, Op0, DAG.getConstant(0, MVT::i1), NewCC);
|
||||
}
|
||||
|
||||
unsigned X86CC;
|
||||
SDValue EFLAGS = EmitCmp(Op0, Op1, CC, dl, DAG, X86CC);
|
||||
if (!EFLAGS.getNode())
|
||||
bool isFP = Op1.getSimpleValueType().isFloatingPoint();
|
||||
unsigned X86CC = TranslateX86CC(CC, isFP, Op0, Op1, DAG);
|
||||
if (X86CC == X86::COND_INVALID)
|
||||
return SDValue();
|
||||
|
||||
SDValue EFLAGS = EmitCmp(Op0, Op1, X86CC, dl, DAG);
|
||||
EFLAGS = ConvertCmpIfNecessary(EFLAGS, DAG);
|
||||
SDValue SetCC = DAG.getNode(X86ISD::SETCC, dl, MVT::i8,
|
||||
DAG.getConstant(X86CC, MVT::i8), EFLAGS);
|
||||
@ -11456,14 +11384,6 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
|
||||
if (isX86LogicalCmp(Cmp) || Opc == X86ISD::BT) {
|
||||
Cond = Cmp;
|
||||
addTest = false;
|
||||
} else if (Opc == ISD::CopyFromReg &&
|
||||
Cmp->getOperand(0)->getOpcode() == ISD::CopyFromReg &&
|
||||
Cmp->getOperand(0)->getOperand(0)->getOpcode() ==
|
||||
X86ISD::LCMPXCHG_DAG) {
|
||||
assert(cast<RegisterSDNode>(Cmp->getOperand(1))->getReg() == X86::EFLAGS);
|
||||
Chain = Cmp.getValue(1);
|
||||
Cond = Cmp;
|
||||
addTest = false;
|
||||
} else {
|
||||
switch (cast<ConstantSDNode>(CC)->getZExtValue()) {
|
||||
default: break;
|
||||
@ -14443,6 +14363,38 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, const X86Subtarget *Subtarget,
|
||||
return DAG.getNode(X86ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
|
||||
}
|
||||
|
||||
static SDValue LowerCMP_SWAP(SDValue Op, const X86Subtarget *Subtarget,
|
||||
SelectionDAG &DAG) {
|
||||
MVT T = Op.getSimpleValueType();
|
||||
SDLoc DL(Op);
|
||||
unsigned Reg = 0;
|
||||
unsigned size = 0;
|
||||
switch(T.SimpleTy) {
|
||||
default: llvm_unreachable("Invalid value type!");
|
||||
case MVT::i8: Reg = X86::AL; size = 1; break;
|
||||
case MVT::i16: Reg = X86::AX; size = 2; break;
|
||||
case MVT::i32: Reg = X86::EAX; size = 4; break;
|
||||
case MVT::i64:
|
||||
assert(Subtarget->is64Bit() && "Node not type legal!");
|
||||
Reg = X86::RAX; size = 8;
|
||||
break;
|
||||
}
|
||||
SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), DL, Reg,
|
||||
Op.getOperand(2), SDValue());
|
||||
SDValue Ops[] = { cpIn.getValue(0),
|
||||
Op.getOperand(1),
|
||||
Op.getOperand(3),
|
||||
DAG.getTargetConstant(size, MVT::i8),
|
||||
cpIn.getValue(1) };
|
||||
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||
MachineMemOperand *MMO = cast<AtomicSDNode>(Op)->getMemOperand();
|
||||
SDValue Result = DAG.getMemIntrinsicNode(X86ISD::LCMPXCHG_DAG, DL, Tys,
|
||||
Ops, T, MMO);
|
||||
SDValue cpOut =
|
||||
DAG.getCopyFromReg(Result.getValue(0), DL, Reg, T, Result.getValue(1));
|
||||
return cpOut;
|
||||
}
|
||||
|
||||
static SDValue LowerBITCAST(SDValue Op, const X86Subtarget *Subtarget,
|
||||
SelectionDAG &DAG) {
|
||||
MVT SrcVT = Op.getOperand(0).getSimpleValueType();
|
||||
|
@ -1006,10 +1006,9 @@ namespace llvm {
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
/// Emit nodes that will be selected as "cmp Op0,Op1", or something
|
||||
/// equivalent, possibly adjusting the condition code to a more appropriate
|
||||
/// x86 form.
|
||||
SDValue EmitCmp(SDValue Op0, SDValue Op1, ISD::CondCode CC, SDLoc dl,
|
||||
SelectionDAG &DAG, unsigned &X86CC) const;
|
||||
/// equivalent, for use with the given x86 condition code.
|
||||
SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, SDLoc dl,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
/// Convert a comparison if required by the subtarget.
|
||||
SDValue ConvertCmpIfNecessary(SDValue Cmp, SelectionDAG &DAG) const;
|
||||
|
@ -1,82 +0,0 @@
|
||||
; RUN: llc -mtriple=x86_64 -o - %s | FileCheck %s
|
||||
|
||||
define i1 @try_cmpxchg(i32* %addr, i32 %desired, i32 %new) {
|
||||
; CHECK-LABEL: try_cmpxchg:
|
||||
; CHECK: cmpxchgl
|
||||
; CHECK-NOT: cmp
|
||||
; CHECK: sete %al
|
||||
; CHECK: retq
|
||||
%old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
|
||||
%success = icmp eq i32 %old, %desired
|
||||
ret i1 %success
|
||||
}
|
||||
|
||||
define void @cmpxchg_flow(i64* %addr, i64 %desired, i64 %new) {
|
||||
; CHECK-LABEL: cmpxchg_flow:
|
||||
; CHECK: cmpxchgq
|
||||
; CHECK-NOT: cmp
|
||||
; CHECK-NOT: set
|
||||
; CHECK: {{jne|jeq}}
|
||||
%old = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst seq_cst
|
||||
%success = icmp eq i64 %old, %desired
|
||||
br i1 %success, label %true, label %false
|
||||
|
||||
true:
|
||||
call void @foo()
|
||||
ret void
|
||||
|
||||
false:
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
|
||||
define i1 @cmpxchg_arithcmp(i16* %addr, i16 %desired, i16 %new) {
|
||||
; CHECK-LABEL: cmpxchg_arithcmp:
|
||||
; CHECK: cmpxchgw
|
||||
; CHECK-NOT: cmp
|
||||
; CHECK: setbe %al
|
||||
; CHECK: retq
|
||||
%old = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst seq_cst
|
||||
%success = icmp uge i16 %old, %desired
|
||||
ret i1 %success
|
||||
}
|
||||
|
||||
define i1 @cmpxchg_arithcmp_swapped(i8* %addr, i8 %desired, i8 %new) {
|
||||
; CHECK-LABEL: cmpxchg_arithcmp_swapped:
|
||||
; CHECK: cmpxchgb
|
||||
; CHECK-NOT: cmp
|
||||
; CHECK: setge %al
|
||||
; CHECK: retq
|
||||
%old = cmpxchg i8* %addr, i8 %desired, i8 %new seq_cst seq_cst
|
||||
%success = icmp sge i8 %desired, %old
|
||||
ret i1 %success
|
||||
}
|
||||
|
||||
define i64 @cmpxchg_sext(i32* %addr, i32 %desired, i32 %new) {
|
||||
; CHECK-LABEL: cmpxchg_sext:
|
||||
; CHECK-DAG: cmpxchgl
|
||||
; CHECK-DAG: movq $-1, %rax
|
||||
; CHECK-DAG: xorl %e[[ZERO:[a-z0-9]+]], %e[[ZERO]]
|
||||
; CHECK-NOT: cmpl
|
||||
; CHECK: cmovneq %r[[ZERO]], %rax
|
||||
; CHECK: retq
|
||||
%old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
|
||||
%success = icmp eq i32 %old, %desired
|
||||
%mask = sext i1 %success to i64
|
||||
ret i64 %mask
|
||||
}
|
||||
|
||||
define i32 @cmpxchg_zext(i32* %addr, i32 %desired, i32 %new) {
|
||||
; CHECK-LABEL: cmpxchg_zext:
|
||||
; CHECK: cmpxchgl
|
||||
; CHECK-NOT: cmp
|
||||
; CHECK: sete [[BYTE:%[a-z0-9]+]]
|
||||
; CHECK: movzbl [[BYTE]], %eax
|
||||
%old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
|
||||
%success = icmp eq i32 %old, %desired
|
||||
%mask = zext i1 %success to i32
|
||||
ret i32 %mask
|
||||
}
|
||||
|
||||
declare void @foo()
|
||||
declare void @bar()
|
Loading…
Reference in New Issue
Block a user