Framework for atomic binary operations. The emitter for the pseudo instructions

just issues an error for the moment. The front end won't yet generate these
intrinsics for ARM, so this is behind the scenes until complete.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91200 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2009-12-12 01:40:06 +00:00
parent 73a1b67cb9
commit e801dc4a7b
3 changed files with 150 additions and 19 deletions

View File

@ -42,6 +42,7 @@
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <sstream> #include <sstream>
using namespace llvm; using namespace llvm;
@ -3043,8 +3044,9 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
MachineBasicBlock * MachineBasicBlock *
ARMTargetLowering::EmitAtomicCmpSwap(unsigned Size, MachineInstr *MI, ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
MachineBasicBlock *BB) const { MachineBasicBlock *BB,
unsigned Size) const {
unsigned dest = MI->getOperand(0).getReg(); unsigned dest = MI->getOperand(0).getReg();
unsigned ptr = MI->getOperand(1).getReg(); unsigned ptr = MI->getOperand(1).getReg();
unsigned oldval = MI->getOperand(2).getReg(); unsigned oldval = MI->getOperand(2).getReg();
@ -3113,6 +3115,16 @@ ARMTargetLowering::EmitAtomicCmpSwap(unsigned Size, MachineInstr *MI,
return BB; return BB;
} }
MachineBasicBlock *
ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode) const {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Cannot yet emit: ";
MI->print(Msg);
llvm_report_error(Msg.str());
}
MachineBasicBlock * MachineBasicBlock *
ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB, MachineBasicBlock *BB,
@ -3124,12 +3136,37 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MI->dump(); MI->dump();
llvm_unreachable("Unexpected instr type to insert"); llvm_unreachable("Unexpected instr type to insert");
case ARM::ATOMIC_LOAD_ADD_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ADDrr);
case ARM::ATOMIC_LOAD_ADD_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ADDrr);
case ARM::ATOMIC_LOAD_ADD_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ADDrr);
case ARM::ATOMIC_LOAD_AND_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ANDrr);
case ARM::ATOMIC_LOAD_AND_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ANDrr);
case ARM::ATOMIC_LOAD_AND_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ANDrr);
case ARM::ATOMIC_LOAD_OR_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ORRrr);
case ARM::ATOMIC_LOAD_OR_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ORRrr);
case ARM::ATOMIC_LOAD_OR_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ORRrr);
case ARM::ATOMIC_CMP_SWAP_I8: return EmitAtomicCmpSwap(1, MI, BB); case ARM::ATOMIC_LOAD_XOR_I8: return EmitAtomicBinary(MI, BB, 1, ARM::EORrr);
case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(2, MI, BB); case ARM::ATOMIC_LOAD_XOR_I16: return EmitAtomicBinary(MI, BB, 2, ARM::EORrr);
case ARM::ATOMIC_CMP_SWAP_I32: return EmitAtomicCmpSwap(4, MI, BB); case ARM::ATOMIC_LOAD_XOR_I32: return EmitAtomicBinary(MI, BB, 4, ARM::EORrr);
case ARM::ATOMIC_LOAD_NAND_I8: return EmitAtomicBinary(MI, BB, 1, ARM::BICrr);
case ARM::ATOMIC_LOAD_NAND_I16:return EmitAtomicBinary(MI, BB, 2, ARM::BICrr);
case ARM::ATOMIC_LOAD_NAND_I32:return EmitAtomicBinary(MI, BB, 4, ARM::BICrr);
case ARM::ATOMIC_LOAD_SUB_I8: return EmitAtomicBinary(MI, BB, 1, ARM::SUBrr);
case ARM::ATOMIC_LOAD_SUB_I16: return EmitAtomicBinary(MI, BB, 2, ARM::SUBrr);
case ARM::ATOMIC_LOAD_SUB_I32: return EmitAtomicBinary(MI, BB, 4, ARM::SUBrr);
case ARM::ATOMIC_SWAP_I8: return EmitAtomicBinary(MI, BB, 1, 0);
case ARM::ATOMIC_SWAP_I16: return EmitAtomicBinary(MI, BB, 2, 0);
case ARM::ATOMIC_SWAP_I32: return EmitAtomicBinary(MI, BB, 4, 0);
case ARM::ATOMIC_CMP_SWAP_I8: return EmitAtomicCmpSwap(MI, BB, 1);
case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(MI, BB, 2);
case ARM::ATOMIC_CMP_SWAP_I32: return EmitAtomicCmpSwap(MI, BB, 4);
case ARM::tMOVCCr_pseudo: { case ARM::tMOVCCr_pseudo: {
// To "insert" a SELECT_CC instruction, we actually have to insert the // To "insert" a SELECT_CC instruction, we actually have to insert the

View File

@ -332,8 +332,13 @@ namespace llvm {
SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl); SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl);
MachineBasicBlock *EmitAtomicCmpSwap(unsigned Size, MachineInstr *MI, MachineBasicBlock *EmitAtomicCmpSwap(MachineInstr *MI,
MachineBasicBlock *BB) const; MachineBasicBlock *BB,
unsigned Size) const;
MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI,
MachineBasicBlock *BB,
unsigned Size,
unsigned BinOpcode) const;
}; };
} }

View File

@ -1597,18 +1597,107 @@ def Int_SyncBarrierV7 : AI<(outs), (ins),
} }
let usesCustomInserter = 1 in { let usesCustomInserter = 1 in {
def ATOMIC_CMP_SWAP_I8 : PseudoInst< let Uses = [CPSR] in {
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, def ATOMIC_LOAD_ADD_I8 : PseudoInst<
"${:comment} ATOMIC_CMP_SWAP_I8 PSEUDO!", (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
[(set GPR:$dst, (atomic_cmp_swap_8 GPR:$ptr, GPR:$old, GPR:$new))]>; "${:comment} ATOMIC_LOAD_ADD_I8 PSEUDO!",
def ATOMIC_CMP_SWAP_I16 : PseudoInst< [(set GPR:$dst, (atomic_load_add_8 GPR:$ptr, GPR:$incr))]>;
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, def ATOMIC_LOAD_SUB_I8 : PseudoInst<
"${:comment} ATOMIC_CMP_SWAP_I16 PSEUDO!", (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
[(set GPR:$dst, (atomic_cmp_swap_16 GPR:$ptr, GPR:$old, GPR:$new))]>; "${:comment} ATOMIC_LOAD_SUB_I8 PSEUDO!",
def ATOMIC_CMP_SWAP_I32 : PseudoInst< [(set GPR:$dst, (atomic_load_sub_8 GPR:$ptr, GPR:$incr))]>;
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, def ATOMIC_LOAD_AND_I8 : PseudoInst<
"${:comment} ATOMIC_CMP_SWAP_I32 PSEUDO!", (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
[(set GPR:$dst, (atomic_cmp_swap_32 GPR:$ptr, GPR:$old, GPR:$new))]>; "${:comment} ATOMIC_LOAD_AND_I8 PSEUDO!",
[(set GPR:$dst, (atomic_load_and_8 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_OR_I8 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_OR_I8 PSEUDO!",
[(set GPR:$dst, (atomic_load_or_8 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_XOR_I8 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_XOR_I8 PSEUDO!",
[(set GPR:$dst, (atomic_load_xor_8 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_NAND_I8 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_NAND_I8 PSEUDO!",
[(set GPR:$dst, (atomic_load_nand_8 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_ADD_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_ADD_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_add_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_SUB_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_SUB_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_sub_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_AND_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_AND_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_and_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_OR_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_OR_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_or_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_XOR_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_XOR_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_xor_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_NAND_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_NAND_I16 PSEUDO!",
[(set GPR:$dst, (atomic_load_nand_16 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_ADD_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_ADD_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_SUB_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_SUB_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_sub_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_AND_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_AND_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_and_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_OR_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_OR_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_or_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_XOR_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_XOR_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_xor_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_LOAD_NAND_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary,
"${:comment} ATOMIC_LOAD_NAND_I32 PSEUDO!",
[(set GPR:$dst, (atomic_load_nand_32 GPR:$ptr, GPR:$incr))]>;
def ATOMIC_SWAP_I8 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary,
"${:comment} ATOMIC_SWAP_I8 PSEUDO!",
[(set GPR:$dst, (atomic_swap_8 GPR:$ptr, GPR:$new))]>;
def ATOMIC_SWAP_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary,
"${:comment} ATOMIC_SWAP_I16 PSEUDO!",
[(set GPR:$dst, (atomic_swap_16 GPR:$ptr, GPR:$new))]>;
def ATOMIC_SWAP_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary,
"${:comment} ATOMIC_SWAP_I32 PSEUDO!",
[(set GPR:$dst, (atomic_swap_32 GPR:$ptr, GPR:$new))]>;
def ATOMIC_CMP_SWAP_I8 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary,
"${:comment} ATOMIC_CMP_SWAP_I8 PSEUDO!",
[(set GPR:$dst, (atomic_cmp_swap_8 GPR:$ptr, GPR:$old, GPR:$new))]>;
def ATOMIC_CMP_SWAP_I16 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary,
"${:comment} ATOMIC_CMP_SWAP_I16 PSEUDO!",
[(set GPR:$dst, (atomic_cmp_swap_16 GPR:$ptr, GPR:$old, GPR:$new))]>;
def ATOMIC_CMP_SWAP_I32 : PseudoInst<
(outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary,
"${:comment} ATOMIC_CMP_SWAP_I32 PSEUDO!",
[(set GPR:$dst, (atomic_cmp_swap_32 GPR:$ptr, GPR:$old, GPR:$new))]>;
}
} }
let mayLoad = 1 in { let mayLoad = 1 in {