mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Refactor X86SelectConstAddr, folding it into X86SelectAddress. This
results in better code for globals. Also, unbreak the local CSE for GlobalValue stub loads. llvm-svn: 56371
This commit is contained in:
parent
312df3aa6d
commit
f66b3277d3
@ -44,15 +44,10 @@ unsigned FastISel::getRegForValue(Value *V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||||
if (CI->getValue().getActiveBits() > 64)
|
if (CI->getValue().getActiveBits() <= 64)
|
||||||
return TargetMaterializeConstant(CI);
|
Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
|
||||||
// Don't cache constant materializations. To do so would require
|
|
||||||
// tracking what uses they dominate.
|
|
||||||
Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
|
|
||||||
} else if (isa<GlobalValue>(V)) {
|
|
||||||
return TargetMaterializeConstant(cast<Constant>(V));
|
|
||||||
} else if (isa<AllocaInst>(V)) {
|
} else if (isa<AllocaInst>(V)) {
|
||||||
return TargetMaterializeAlloca(cast<AllocaInst>(V));
|
Reg = TargetMaterializeAlloca(cast<AllocaInst>(V));
|
||||||
} else if (isa<ConstantPointerNull>(V)) {
|
} else if (isa<ConstantPointerNull>(V)) {
|
||||||
Reg = FastEmit_i(VT, VT, ISD::Constant, 0);
|
Reg = FastEmit_i(VT, VT, ISD::Constant, 0);
|
||||||
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
|
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
|
||||||
@ -64,18 +59,15 @@ unsigned FastISel::getRegForValue(Value *V) {
|
|||||||
|
|
||||||
uint64_t x[2];
|
uint64_t x[2];
|
||||||
uint32_t IntBitWidth = IntVT.getSizeInBits();
|
uint32_t IntBitWidth = IntVT.getSizeInBits();
|
||||||
if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
|
if (!Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
|
||||||
APFloat::rmTowardZero) != APFloat::opOK)
|
APFloat::rmTowardZero) != APFloat::opOK) {
|
||||||
return TargetMaterializeConstant(CF);
|
APInt IntVal(IntBitWidth, 2, x);
|
||||||
APInt IntVal(IntBitWidth, 2, x);
|
|
||||||
|
|
||||||
unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(),
|
unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(),
|
||||||
ISD::Constant, IntVal.getZExtValue());
|
ISD::Constant, IntVal.getZExtValue());
|
||||||
if (IntegerReg == 0)
|
if (IntegerReg != 0)
|
||||||
return TargetMaterializeConstant(CF);
|
Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg);
|
||||||
Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg);
|
}
|
||||||
if (Reg == 0)
|
|
||||||
return TargetMaterializeConstant(CF);
|
|
||||||
}
|
}
|
||||||
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||||
if (!SelectOperator(CE, CE->getOpcode())) return 0;
|
if (!SelectOperator(CE, CE->getOpcode())) return 0;
|
||||||
@ -88,8 +80,10 @@ unsigned FastISel::getRegForValue(Value *V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Reg && isa<Constant>(V))
|
if (!Reg && isa<Constant>(V))
|
||||||
return TargetMaterializeConstant(cast<Constant>(V));
|
Reg = TargetMaterializeConstant(cast<Constant>(V));
|
||||||
|
|
||||||
|
// Don't cache constant materializations in the general ValueMap.
|
||||||
|
// To do so would require tracking what uses they dominate.
|
||||||
LocalValueMap[V] = Reg;
|
LocalValueMap[V] = Reg;
|
||||||
return Reg;
|
return Reg;
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,7 @@ private:
|
|||||||
bool X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, unsigned Src, MVT SrcVT,
|
bool X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, unsigned Src, MVT SrcVT,
|
||||||
unsigned &ResultReg);
|
unsigned &ResultReg);
|
||||||
|
|
||||||
bool X86SelectConstAddr(Value *V, unsigned &Op0,
|
bool X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall);
|
||||||
bool isCall = false, bool inReg = false);
|
|
||||||
|
|
||||||
bool X86SelectAddress(Value *V, X86AddressMode &AM);
|
|
||||||
|
|
||||||
bool X86SelectLoad(Instruction *I);
|
bool X86SelectLoad(Instruction *I);
|
||||||
|
|
||||||
@ -281,56 +278,9 @@ bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// X86SelectConstAddr - Select and emit code to materialize constant address.
|
|
||||||
///
|
|
||||||
bool X86FastISel::X86SelectConstAddr(Value *V, unsigned &Op0,
|
|
||||||
bool isCall, bool inReg) {
|
|
||||||
// FIXME: Only GlobalAddress for now.
|
|
||||||
GlobalValue *GV = dyn_cast<GlobalValue>(V);
|
|
||||||
if (!GV)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Subtarget->GVRequiresExtraLoad(GV, TM, isCall)) {
|
|
||||||
// Issue load from stub if necessary.
|
|
||||||
unsigned Opc = 0;
|
|
||||||
const TargetRegisterClass *RC = NULL;
|
|
||||||
if (TLI.getPointerTy() == MVT::i32) {
|
|
||||||
Opc = X86::MOV32rm;
|
|
||||||
RC = X86::GR32RegisterClass;
|
|
||||||
} else {
|
|
||||||
Opc = X86::MOV64rm;
|
|
||||||
RC = X86::GR64RegisterClass;
|
|
||||||
}
|
|
||||||
Op0 = createResultReg(RC);
|
|
||||||
X86AddressMode AM;
|
|
||||||
AM.GV = GV;
|
|
||||||
addFullAddress(BuildMI(MBB, TII.get(Opc), Op0), AM);
|
|
||||||
// Prevent loading GV stub multiple times in same MBB.
|
|
||||||
LocalValueMap[V] = Op0;
|
|
||||||
} else if (inReg) {
|
|
||||||
unsigned Opc = 0;
|
|
||||||
const TargetRegisterClass *RC = NULL;
|
|
||||||
if (TLI.getPointerTy() == MVT::i32) {
|
|
||||||
Opc = X86::LEA32r;
|
|
||||||
RC = X86::GR32RegisterClass;
|
|
||||||
} else {
|
|
||||||
Opc = X86::LEA64r;
|
|
||||||
RC = X86::GR64RegisterClass;
|
|
||||||
}
|
|
||||||
Op0 = createResultReg(RC);
|
|
||||||
X86AddressMode AM;
|
|
||||||
AM.GV = GV;
|
|
||||||
addFullAddress(BuildMI(MBB, TII.get(Opc), Op0), AM);
|
|
||||||
// Prevent materializing GV address multiple times in same MBB.
|
|
||||||
LocalValueMap[V] = Op0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// X86SelectAddress - Attempt to fill in an address from the given value.
|
/// X86SelectAddress - Attempt to fill in an address from the given value.
|
||||||
///
|
///
|
||||||
bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
|
bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
|
||||||
User *U;
|
User *U;
|
||||||
unsigned Opcode = Instruction::UserOp1;
|
unsigned Opcode = Instruction::UserOp1;
|
||||||
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||||
@ -345,19 +295,20 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
|
|||||||
default: break;
|
default: break;
|
||||||
case Instruction::BitCast:
|
case Instruction::BitCast:
|
||||||
// Look past bitcasts.
|
// Look past bitcasts.
|
||||||
return X86SelectAddress(U->getOperand(0), AM);
|
return X86SelectAddress(U->getOperand(0), AM, isCall);
|
||||||
|
|
||||||
case Instruction::IntToPtr:
|
case Instruction::IntToPtr:
|
||||||
// Look past no-op inttoptrs.
|
// Look past no-op inttoptrs.
|
||||||
if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
|
if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
|
||||||
return X86SelectAddress(U->getOperand(0), AM);
|
return X86SelectAddress(U->getOperand(0), AM, isCall);
|
||||||
|
|
||||||
case Instruction::PtrToInt:
|
case Instruction::PtrToInt:
|
||||||
// Look past no-op ptrtoints.
|
// Look past no-op ptrtoints.
|
||||||
if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
|
if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
|
||||||
return X86SelectAddress(U->getOperand(0), AM);
|
return X86SelectAddress(U->getOperand(0), AM, isCall);
|
||||||
|
|
||||||
case Instruction::Alloca: {
|
case Instruction::Alloca: {
|
||||||
|
if (isCall) break;
|
||||||
// Do static allocas.
|
// Do static allocas.
|
||||||
const AllocaInst *A = cast<AllocaInst>(V);
|
const AllocaInst *A = cast<AllocaInst>(V);
|
||||||
DenseMap<const AllocaInst*, int>::iterator SI = StaticAllocaMap.find(A);
|
DenseMap<const AllocaInst*, int>::iterator SI = StaticAllocaMap.find(A);
|
||||||
@ -369,15 +320,17 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Instruction::Add: {
|
case Instruction::Add: {
|
||||||
|
if (isCall) break;
|
||||||
// Adds of constants are common and easy enough.
|
// Adds of constants are common and easy enough.
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(U->getOperand(1))) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(U->getOperand(1))) {
|
||||||
AM.Disp += CI->getZExtValue();
|
AM.Disp += CI->getZExtValue();
|
||||||
return X86SelectAddress(U->getOperand(0), AM);
|
return X86SelectAddress(U->getOperand(0), AM, isCall);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Instruction::GetElementPtr: {
|
case Instruction::GetElementPtr: {
|
||||||
|
if (isCall) break;
|
||||||
// Pattern-match simple GEPs.
|
// Pattern-match simple GEPs.
|
||||||
uint64_t Disp = AM.Disp;
|
uint64_t Disp = AM.Disp;
|
||||||
unsigned IndexReg = AM.IndexReg;
|
unsigned IndexReg = AM.IndexReg;
|
||||||
@ -414,7 +367,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
|
|||||||
AM.IndexReg = IndexReg;
|
AM.IndexReg = IndexReg;
|
||||||
AM.Scale = Scale;
|
AM.Scale = Scale;
|
||||||
AM.Disp = Disp;
|
AM.Disp = Disp;
|
||||||
return X86SelectAddress(U->getOperand(0), AM);
|
return X86SelectAddress(U->getOperand(0), AM, isCall);
|
||||||
unsupported_gep:
|
unsupported_gep:
|
||||||
// Ok, the GEP indices weren't all covered.
|
// Ok, the GEP indices weren't all covered.
|
||||||
break;
|
break;
|
||||||
@ -422,19 +375,37 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle constant address.
|
// Handle constant address.
|
||||||
// FIXME: If load type is something we can't handle, this can result in
|
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||||
// a dead stub load instruction.
|
if (Subtarget->GVRequiresExtraLoad(GV, TM, isCall)) {
|
||||||
if (isa<Constant>(V) && X86SelectConstAddr(V, AM.Base.Reg)) {
|
// Check to see if we've already materialized this
|
||||||
if (AM.Base.Reg == 0)
|
// value in a register in this block.
|
||||||
AM.GV = cast<GlobalValue>(V);
|
if (unsigned Reg = LocalValueMap[V])
|
||||||
} else {
|
return Reg;
|
||||||
AM.Base.Reg = getRegForValue(V);
|
// Issue load from stub if necessary.
|
||||||
if (AM.Base.Reg == 0)
|
unsigned Opc = 0;
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
const TargetRegisterClass *RC = NULL;
|
||||||
return false;
|
if (TLI.getPointerTy() == MVT::i32) {
|
||||||
|
Opc = X86::MOV32rm;
|
||||||
|
RC = X86::GR32RegisterClass;
|
||||||
|
} else {
|
||||||
|
Opc = X86::MOV64rm;
|
||||||
|
RC = X86::GR64RegisterClass;
|
||||||
|
}
|
||||||
|
AM.Base.Reg = createResultReg(RC);
|
||||||
|
X86AddressMode LocalAM;
|
||||||
|
LocalAM.GV = GV;
|
||||||
|
addFullAddress(BuildMI(MBB, TII.get(Opc), AM.Base.Reg), LocalAM);
|
||||||
|
// Prevent loading GV stub multiple times in same MBB.
|
||||||
|
LocalValueMap[V] = AM.Base.Reg;
|
||||||
|
} else {
|
||||||
|
AM.GV = GV;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
// If all else fails, just materialize the value in a register.
|
||||||
|
AM.Base.Reg = getRegForValue(V);
|
||||||
|
return AM.Base.Reg != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// X86SelectStore - Select and emit code to implement store instructions.
|
/// X86SelectStore - Select and emit code to implement store instructions.
|
||||||
@ -448,7 +419,7 @@ bool X86FastISel::X86SelectStore(Instruction* I) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
X86AddressMode AM;
|
X86AddressMode AM;
|
||||||
if (!X86SelectAddress(I->getOperand(1), AM))
|
if (!X86SelectAddress(I->getOperand(1), AM, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return X86FastEmitStore(VT, Val, AM);
|
return X86FastEmitStore(VT, Val, AM);
|
||||||
@ -462,7 +433,7 @@ bool X86FastISel::X86SelectLoad(Instruction *I) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
X86AddressMode AM;
|
X86AddressMode AM;
|
||||||
if (!X86SelectAddress(I->getOperand(0), AM))
|
if (!X86SelectAddress(I->getOperand(0), AM, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned ResultReg = 0;
|
unsigned ResultReg = 0;
|
||||||
@ -849,13 +820,19 @@ bool X86FastISel::X86SelectCall(Instruction *I) {
|
|||||||
|
|
||||||
// Materialize callee address in a register. FIXME: GV address can be
|
// Materialize callee address in a register. FIXME: GV address can be
|
||||||
// handled with a CALLpcrel32 instead.
|
// handled with a CALLpcrel32 instead.
|
||||||
|
X86AddressMode CalleeAM;
|
||||||
|
if (!X86SelectAddress(Callee, CalleeAM, true))
|
||||||
|
return false;
|
||||||
unsigned CalleeOp = 0;
|
unsigned CalleeOp = 0;
|
||||||
if (!isa<Constant>(Callee) || !X86SelectConstAddr(Callee, CalleeOp, true)) {
|
GlobalValue *GV = 0;
|
||||||
CalleeOp = getRegForValue(Callee);
|
if (CalleeAM.Base.Reg != 0) {
|
||||||
if (CalleeOp == 0)
|
assert(CalleeAM.GV == 0);
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
CalleeOp = CalleeAM.Base.Reg;
|
||||||
return false;
|
} else if (CalleeAM.GV != 0) {
|
||||||
}
|
assert(CalleeAM.GV != 0);
|
||||||
|
GV = CalleeAM.GV;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
// Allow calls which produce i1 results.
|
// Allow calls which produce i1 results.
|
||||||
bool AndToI1 = false;
|
bool AndToI1 = false;
|
||||||
@ -976,7 +953,7 @@ bool X86FastISel::X86SelectCall(Instruction *I) {
|
|||||||
: (Subtarget->is64Bit() ? X86::CALL64pcrel32 : X86::CALLpcrel32);
|
: (Subtarget->is64Bit() ? X86::CALL64pcrel32 : X86::CALLpcrel32);
|
||||||
MachineInstrBuilder MIB = CalleeOp
|
MachineInstrBuilder MIB = CalleeOp
|
||||||
? BuildMI(MBB, TII.get(CallOpc)).addReg(CalleeOp)
|
? BuildMI(MBB, TII.get(CallOpc)).addReg(CalleeOp)
|
||||||
:BuildMI(MBB, TII.get(CallOpc)).addGlobalAddress(cast<GlobalValue>(Callee));
|
: BuildMI(MBB, TII.get(CallOpc)).addGlobalAddress(GV);
|
||||||
// Add implicit physical register uses to the call.
|
// Add implicit physical register uses to the call.
|
||||||
while (!RegArgs.empty()) {
|
while (!RegArgs.empty()) {
|
||||||
MIB.addReg(RegArgs.back());
|
MIB.addReg(RegArgs.back());
|
||||||
@ -1132,10 +1109,18 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ResultReg = createResultReg(RC);
|
// Materialize addresses with LEA instructions.
|
||||||
if (isa<GlobalValue>(C)) {
|
if (isa<GlobalValue>(C)) {
|
||||||
if (X86SelectConstAddr(C, ResultReg, false, true))
|
X86AddressMode AM;
|
||||||
|
if (X86SelectAddress(C, AM, false)) {
|
||||||
|
if (TLI.getPointerTy() == MVT::i32)
|
||||||
|
Opc = X86::LEA32r;
|
||||||
|
else
|
||||||
|
Opc = X86::LEA64r;
|
||||||
|
unsigned ResultReg = createResultReg(RC);
|
||||||
|
addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM);
|
||||||
return ResultReg;
|
return ResultReg;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,13 +1133,14 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned MCPOffset = MCP.getConstantPoolIndex(C, Align);
|
unsigned MCPOffset = MCP.getConstantPoolIndex(C, Align);
|
||||||
|
unsigned ResultReg = createResultReg(RC);
|
||||||
addConstantPoolReference(BuildMI(MBB, TII.get(Opc), ResultReg), MCPOffset);
|
addConstantPoolReference(BuildMI(MBB, TII.get(Opc), ResultReg), MCPOffset);
|
||||||
return ResultReg;
|
return ResultReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) {
|
unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) {
|
||||||
X86AddressMode AM;
|
X86AddressMode AM;
|
||||||
if (!X86SelectAddress(C, AM))
|
if (!X86SelectAddress(C, AM, false))
|
||||||
return 0;
|
return 0;
|
||||||
unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r;
|
unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r;
|
||||||
TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy());
|
TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
; RUN: llvm-as < %s | llc -fast-isel -mtriple=i386-apple-darwin | \
|
; RUN: llvm-as < %s | llc -fast-isel -mtriple=i386-apple-darwin | \
|
||||||
; RUN: grep mov | grep lazy_ptr | count 2
|
; RUN: grep lazy_ptr, | count 2
|
||||||
; RUN: llvm-as < %s | llc -fast-isel -march=x86 -relocation-model=static | \
|
; RUN: llvm-as < %s | llc -fast-isel -march=x86 -relocation-model=static | \
|
||||||
; RUN: grep lea
|
; RUN: grep lea
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user