| Index: src/IceTargetLoweringX8632.cpp
|
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
|
| index 449e41378df44a6f5a0e5c23fd4fc5fc8d903966..212bfec2658c8acff360c06c73e99de699416dd7 100644
|
| --- a/src/IceTargetLoweringX8632.cpp
|
| +++ b/src/IceTargetLoweringX8632.cpp
|
| @@ -1600,7 +1600,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
|
| Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode());
|
| Spill->setWeight(RegWeight::Zero);
|
| Spill->setPreferredRegister(llvm::dyn_cast<Variable>(Src0RM), true);
|
| - _mov(Spill, Src0RM);
|
| + _movq(Spill, Src0RM);
|
|
|
| Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
|
| Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
|
| @@ -1640,7 +1640,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
|
| _store(T_Lo, SpillLo);
|
| _mov(T_Hi, hiOperand(Src0RM));
|
| _store(T_Hi, SpillHi);
|
| - _mov(Dest, Spill);
|
| + _movq(Dest, Spill);
|
| } break;
|
| }
|
| break;
|
| @@ -1781,12 +1781,97 @@ void TargetX8632::lowerIcmp(const InstIcmp *Inst) {
|
| void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| switch (Instr->getIntrinsicInfo().ID) {
|
| case Intrinsics::AtomicCmpxchg:
|
| + if (!Intrinsics::VerifyMemoryOrder(
|
| + llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) {
|
| + Func->setError("Unexpected memory order for AtomicCmpxchg");
|
| + return;
|
| + }
|
| + Func->setError("Unhandled intrinsic");
|
| + return;
|
| case Intrinsics::AtomicFence:
|
| + if (!Intrinsics::VerifyMemoryOrder(
|
| + llvm::cast<ConstantInteger>(Instr->getArg(0))->getValue())) {
|
| + Func->setError("Unexpected memory order for AtomicFence");
|
| + return;
|
| + }
|
| + _mfence();
|
| + return;
|
| case Intrinsics::AtomicFenceAll:
|
| - case Intrinsics::AtomicIsLockFree:
|
| - case Intrinsics::AtomicLoad:
|
| + _mfence();
|
| + return;
|
| + case Intrinsics::AtomicIsLockFree: {
|
| + Constant *One = Ctx->getConstantInt(IceType_i32, 1);
|
| + Variable *Dest = Instr->getDest();
|
| + _mov(Dest, One);
|
| + return;
|
| + }
|
| + case Intrinsics::AtomicLoad: {
|
| + // We require the memory address to be naturally aligned.
|
| + // Given that is the case, then normal loads are atomic.
|
| + if (!Intrinsics::VerifyMemoryOrder(
|
| + llvm::cast<ConstantInteger>(Instr->getArg(1))->getValue())) {
|
| + Func->setError("Unexpected memory ordering for AtomicLoad");
|
| + return;
|
| + }
|
| + Variable *Dest = Instr->getDest();
|
| + if (Dest->getType() == IceType_i64) {
|
| + // Follow what GCC does and use a movq instead of what lowerLoad()
|
| + // normally does (split the load into two).
|
| + // Thus, this skips load/arithmetic op folding. Load/arithmetic folding
|
| + // can't happen anyway, since this is x86-32 and integer arithmetic only
|
| + // happens on 32-bit quantities.
|
| + Variable *T = makeReg(IceType_f64);
|
| + OperandX8632Mem *Addr = FormMemoryOperand(Instr->getArg(0), IceType_f64);
|
| + _movq(T, Addr);
|
| + // Then cast the bits back out of the XMM register to the i64 Dest.
|
| + InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, Dest, T);
|
| + lowerCast(Cast);
|
| + return;
|
| + }
|
| + InstLoad *Load = InstLoad::create(Func, Instr->getDest(), Instr->getArg(0));
|
| + lowerLoad(Load);
|
| + return;
|
| + }
|
| case Intrinsics::AtomicRMW:
|
| - case Intrinsics::AtomicStore:
|
| + if (!Intrinsics::VerifyMemoryOrder(
|
| + llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) {
|
| + Func->setError("Unexpected memory ordering for AtomicRMW");
|
| + return;
|
| + }
|
| + lowerAtomicRMW(Instr->getDest(),
|
| + llvm::cast<ConstantInteger>(Instr->getArg(0))->getValue(),
|
| + Instr->getArg(1), Instr->getArg(2));
|
| + return;
|
| + case Intrinsics::AtomicStore: {
|
| + if (!Intrinsics::VerifyMemoryOrder(
|
| + llvm::cast<ConstantInteger>(Instr->getArg(2))->getValue())) {
|
| + Func->setError("Unexpected memory ordering for AtomicStore");
|
| + return;
|
| + }
|
| + // We require the memory address to be naturally aligned.
|
| + // Given that is the case, then normal stores are atomic.
|
| + // Add a fence after the store to make it visible.
|
| + Operand *Value = Instr->getArg(0);
|
| + Operand *Ptr = Instr->getArg(1);
|
| + if (Value->getType() == IceType_i64) {
|
| + // Use a movq instead of what lowerStore() normally does
|
| + // (split the store into two), following what GCC does.
|
| + // Cast the bits from int -> to an xmm register first.
|
| + Variable *T = makeReg(IceType_f64);
|
| + InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, T, Value);
|
| + lowerCast(Cast);
|
| + // Then store XMM w/ a movq.
|
| + OperandX8632Mem *Addr = FormMemoryOperand(Ptr, IceType_f64);
|
| + Addr = llvm::cast<OperandX8632Mem>(legalize(Addr));
|
| + _storeq(T, Addr);
|
| + _mfence();
|
| + return;
|
| + }
|
| + InstStore *Store = InstStore::create(Func, Value, Ptr);
|
| + lowerStore(Store);
|
| + _mfence();
|
| + return;
|
| + }
|
| case Intrinsics::Bswap:
|
| case Intrinsics::Ctlz:
|
| case Intrinsics::Ctpop:
|
| @@ -1798,7 +1883,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| Call->addArg(Instr->getArg(0));
|
| Call->addArg(Instr->getArg(1));
|
| lowerCall(Call);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::Memcpy: {
|
| // In the future, we could potentially emit an inline memcpy/memset, etc.
|
| @@ -1808,7 +1893,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| Call->addArg(Instr->getArg(1));
|
| Call->addArg(Instr->getArg(2));
|
| lowerCall(Call);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::Memmove: {
|
| InstCall *Call = makeHelperCall("memmove", NULL, 3);
|
| @@ -1816,7 +1901,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| Call->addArg(Instr->getArg(1));
|
| Call->addArg(Instr->getArg(2));
|
| lowerCall(Call);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::Memset: {
|
| // The value operand needs to be extended to a stack slot size
|
| @@ -1830,23 +1915,23 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| Call->addArg(ValExt);
|
| Call->addArg(Instr->getArg(2));
|
| lowerCall(Call);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::NaClReadTP: {
|
| - Constant *Zero = Ctx->getConstantInt(IceType_i32, 0);
|
| + Constant *Zero = Ctx->getConstantZero(IceType_i32);
|
| Operand *Src = OperandX8632Mem::create(Func, IceType_i32, NULL, Zero, NULL,
|
| 0, OperandX8632Mem::SegReg_GS);
|
| Variable *Dest = Instr->getDest();
|
| Variable *T = NULL;
|
| _mov(T, Src);
|
| _mov(Dest, T);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::Setjmp: {
|
| InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1);
|
| Call->addArg(Instr->getArg(0));
|
| lowerCall(Call);
|
| - break;
|
| + return;
|
| }
|
| case Intrinsics::Sqrt:
|
| case Intrinsics::Stacksave:
|
| @@ -1855,7 +1940,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| return;
|
| case Intrinsics::Trap:
|
| _ud2();
|
| - break;
|
| + return;
|
| case Intrinsics::UnknownIntrinsic:
|
| Func->setError("Should not be lowering UnknownIntrinsic");
|
| return;
|
| @@ -1863,6 +1948,48 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| return;
|
| }
|
|
|
| +void TargetX8632::lowerAtomicRMW(Variable *Dest, uint32_t Operation,
|
| + Operand *Ptr, Operand *Val) {
|
| + switch (Operation) {
|
| + default:
|
| + Func->setError("Unknown AtomicRMW operation");
|
| + return;
|
| + case Intrinsics::AtomicAdd: {
|
| + if (Dest->getType() == IceType_i64) {
|
| + // Do a nasty cmpxchg8b loop. Factor this into a function.
|
| + Func->setError("Unhandled AtomicRMW operation");
|
| + return;
|
| + }
|
| + // Generate a memory operand from Ptr.
|
| + OperandX8632Mem *Addr = FormMemoryOperand(Ptr, Dest->getType());
|
| + const bool Locked = true;
|
| + Variable *T = NULL;
|
| + _mov(T, Val);
|
| + _xadd(Addr, T, Locked);
|
| + Context.insert(InstFakeDef::create(Func, T));
|
| + _mov(Dest, T);
|
| + break;
|
| + }
|
| + case Intrinsics::AtomicSub: {
|
| + if (Dest->getType() == IceType_i64) {
|
| + // Do a nasty cmpxchg8b loop.
|
| + Func->setError("Unhandled AtomicRMW operation");
|
| + return;
|
| + }
|
| + // Generate a memory operand from Ptr.
|
| + // neg...
|
| + // Then do the same as AtomicAdd.
|
| + break;
|
| + }
|
| + case Intrinsics::AtomicOr:
|
| + case Intrinsics::AtomicAnd:
|
| + case Intrinsics::AtomicXor:
|
| + case Intrinsics::AtomicExchange:
|
| + Func->setError("Unhandled AtomicRMW operation");
|
| + return;
|
| + }
|
| +}
|
| +
|
| namespace {
|
|
|
| bool isAdd(const Inst *Inst) {
|
| @@ -1999,15 +2126,7 @@ void TargetX8632::lowerLoad(const InstLoad *Inst) {
|
| // optimization already creates an OperandX8632Mem operand, so it
|
| // doesn't need another level of transformation.
|
| Type Ty = Inst->getDest()->getType();
|
| - Operand *Src0 = Inst->getSourceAddress();
|
| - // Address mode optimization already creates an OperandX8632Mem
|
| - // operand, so it doesn't need another level of transformation.
|
| - if (!llvm::isa<OperandX8632Mem>(Src0)) {
|
| - Variable *Base = llvm::dyn_cast<Variable>(Src0);
|
| - Constant *Offset = llvm::dyn_cast<Constant>(Src0);
|
| - assert(Base || Offset);
|
| - Src0 = OperandX8632Mem::create(Func, Ty, Base, Offset);
|
| - }
|
| + Operand *Src0 = FormMemoryOperand(Inst->getSourceAddress(), Ty);
|
|
|
| // Fuse this load with a subsequent Arithmetic instruction in the
|
| // following situations:
|
| @@ -2145,18 +2264,7 @@ void TargetX8632::lowerSelect(const InstSelect *Inst) {
|
| void TargetX8632::lowerStore(const InstStore *Inst) {
|
| Operand *Value = Inst->getData();
|
| Operand *Addr = Inst->getAddr();
|
| - OperandX8632Mem *NewAddr = llvm::dyn_cast<OperandX8632Mem>(Addr);
|
| - // Address mode optimization already creates an OperandX8632Mem
|
| - // operand, so it doesn't need another level of transformation.
|
| - if (!NewAddr) {
|
| - // The address will be either a constant (which represents a global
|
| - // variable) or a variable, so either the Base or Offset component
|
| - // of the OperandX8632Mem will be set.
|
| - Variable *Base = llvm::dyn_cast<Variable>(Addr);
|
| - Constant *Offset = llvm::dyn_cast<Constant>(Addr);
|
| - assert(Base || Offset);
|
| - NewAddr = OperandX8632Mem::create(Func, Value->getType(), Base, Offset);
|
| - }
|
| + OperandX8632Mem *NewAddr = FormMemoryOperand(Addr, Value->getType());
|
| NewAddr = llvm::cast<OperandX8632Mem>(legalize(NewAddr));
|
|
|
| if (NewAddr->getType() == IceType_i64) {
|
| @@ -2275,10 +2383,11 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| // need to go in uninitialized registers.
|
| From = Ctx->getConstantZero(From->getType());
|
| }
|
| - bool NeedsReg = !(Allowed & Legal_Imm) ||
|
| + bool NeedsReg =
|
| + !(Allowed & Legal_Imm) ||
|
| // ConstantFloat and ConstantDouble are actually memory operands.
|
| - (!(Allowed & Legal_Mem) && (From->getType() == IceType_f32 ||
|
| - From->getType() == IceType_f64));
|
| + (!(Allowed & Legal_Mem) &&
|
| + (From->getType() == IceType_f32 || From->getType() == IceType_f64));
|
| if (NeedsReg) {
|
| Variable *Reg = makeReg(From->getType(), RegNum);
|
| _mov(Reg, From);
|
| @@ -2311,6 +2420,20 @@ Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap,
|
| return llvm::cast<Variable>(legalize(From, Legal_Reg, AllowOverlap, RegNum));
|
| }
|
|
|
| +OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) {
|
| + OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand);
|
| + // It may be the case that address mode optimization already creates
|
| + // an OperandX8632Mem, so in that case it wouldn't need another level
|
| + // of transformation.
|
| + if (!Mem) {
|
| + Variable *Base = llvm::dyn_cast<Variable>(Operand);
|
| + Constant *Offset = llvm::dyn_cast<Constant>(Operand);
|
| + assert(Base || Offset);
|
| + Mem = OperandX8632Mem::create(Func, Ty, Base, Offset);
|
| + }
|
| + return Mem;
|
| +}
|
| +
|
| Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) {
|
| Variable *Reg = Func->makeVariable(Type, Context.getNode());
|
| if (RegNum == Variable::NoRegister)
|
|
|