Add initial kill flag support to FastISel.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103529 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2010-05-11 23:54:07 +00:00
parent 0efd768aea
commit a6cb641f48
4 changed files with 180 additions and 87 deletions

View File

@ -106,7 +106,7 @@ public:
/// getRegForGEPIndex - This is a wrapper around getRegForValue that also /// getRegForGEPIndex - This is a wrapper around getRegForValue that also
/// takes care of truncating or sign-extending the given getelementptr /// takes care of truncating or sign-extending the given getelementptr
/// index value. /// index value.
unsigned getRegForGEPIndex(const Value *V); std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
virtual ~FastISel(); virtual ~FastISel();
@ -142,7 +142,8 @@ protected:
/// ///
virtual unsigned FastEmit_r(MVT VT, virtual unsigned FastEmit_r(MVT VT,
MVT RetVT, MVT RetVT,
unsigned Opcode, unsigned Op0); unsigned Opcode,
unsigned Op0, bool Op0IsKill);
/// FastEmit_rr - This method is called by target-independent code /// FastEmit_rr - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and /// to request that an instruction with the given type, opcode, and
@ -151,7 +152,8 @@ protected:
virtual unsigned FastEmit_rr(MVT VT, virtual unsigned FastEmit_rr(MVT VT,
MVT RetVT, MVT RetVT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, unsigned Op1); unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill);
/// FastEmit_ri - This method is called by target-independent code /// FastEmit_ri - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and /// to request that an instruction with the given type, opcode, and
@ -160,7 +162,8 @@ protected:
virtual unsigned FastEmit_ri(MVT VT, virtual unsigned FastEmit_ri(MVT VT,
MVT RetVT, MVT RetVT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, uint64_t Imm); unsigned Op0, bool Op0IsKill,
uint64_t Imm);
/// FastEmit_rf - This method is called by target-independent code /// FastEmit_rf - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and /// to request that an instruction with the given type, opcode, and
@ -169,7 +172,8 @@ protected:
virtual unsigned FastEmit_rf(MVT VT, virtual unsigned FastEmit_rf(MVT VT,
MVT RetVT, MVT RetVT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, const ConstantFP *FPImm); unsigned Op0, bool Op0IsKill,
const ConstantFP *FPImm);
/// FastEmit_rri - This method is called by target-independent code /// FastEmit_rri - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and /// to request that an instruction with the given type, opcode, and
@ -178,7 +182,9 @@ protected:
virtual unsigned FastEmit_rri(MVT VT, virtual unsigned FastEmit_rri(MVT VT,
MVT RetVT, MVT RetVT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, unsigned Op1, uint64_t Imm); unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm);
/// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries
/// to emit an instruction with an immediate operand using FastEmit_ri. /// to emit an instruction with an immediate operand using FastEmit_ri.
@ -186,8 +192,8 @@ protected:
/// FastEmit_rr instead. /// FastEmit_rr instead.
unsigned FastEmit_ri_(MVT VT, unsigned FastEmit_ri_(MVT VT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, uint64_t Imm, unsigned Op0, bool Op0IsKill,
MVT ImmType); uint64_t Imm, MVT ImmType);
/// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries
/// to emit an instruction with an immediate operand using FastEmit_rf. /// to emit an instruction with an immediate operand using FastEmit_rf.
@ -195,8 +201,8 @@ protected:
/// FastEmit_rr instead. /// FastEmit_rr instead.
unsigned FastEmit_rf_(MVT VT, unsigned FastEmit_rf_(MVT VT,
unsigned Opcode, unsigned Opcode,
unsigned Op0, const ConstantFP *FPImm, unsigned Op0, bool Op0IsKill,
MVT ImmType); const ConstantFP *FPImm, MVT ImmType);
/// FastEmit_i - This method is called by target-independent code /// FastEmit_i - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and /// to request that an instruction with the given type, opcode, and
@ -225,35 +231,40 @@ protected:
/// ///
unsigned FastEmitInst_r(unsigned MachineInstOpcode, unsigned FastEmitInst_r(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0); unsigned Op0, bool Op0IsKill);
/// FastEmitInst_rr - Emit a MachineInstr with two register operands /// FastEmitInst_rr - Emit a MachineInstr with two register operands
/// and a result register in the given register class. /// and a result register in the given register class.
/// ///
unsigned FastEmitInst_rr(unsigned MachineInstOpcode, unsigned FastEmitInst_rr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, unsigned Op1); unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill);
/// FastEmitInst_ri - Emit a MachineInstr with two register operands /// FastEmitInst_ri - Emit a MachineInstr with two register operands
/// and a result register in the given register class. /// and a result register in the given register class.
/// ///
unsigned FastEmitInst_ri(unsigned MachineInstOpcode, unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, uint64_t Imm); unsigned Op0, bool Op0IsKill,
uint64_t Imm);
/// FastEmitInst_rf - Emit a MachineInstr with two register operands /// FastEmitInst_rf - Emit a MachineInstr with two register operands
/// and a result register in the given register class. /// and a result register in the given register class.
/// ///
unsigned FastEmitInst_rf(unsigned MachineInstOpcode, unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, const ConstantFP *FPImm); unsigned Op0, bool Op0IsKill,
const ConstantFP *FPImm);
/// FastEmitInst_rri - Emit a MachineInstr with two register operands, /// FastEmitInst_rri - Emit a MachineInstr with two register operands,
/// an immediate, and a result register in the given register class. /// an immediate, and a result register in the given register class.
/// ///
unsigned FastEmitInst_rri(unsigned MachineInstOpcode, unsigned FastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, unsigned Op1, uint64_t Imm); unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm);
/// FastEmitInst_i - Emit a MachineInstr with a single immediate /// FastEmitInst_i - Emit a MachineInstr with a single immediate
/// operand, and a result register in the given register class. /// operand, and a result register in the given register class.
@ -264,12 +275,13 @@ protected:
/// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg
/// from a specified index of a superregister to a specified type. /// from a specified index of a superregister to a specified type.
unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned FastEmitInst_extractsubreg(MVT RetVT,
unsigned Op0, uint32_t Idx); unsigned Op0, bool Op0IsKill,
uint32_t Idx);
/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op
/// with all but the least significant bit set to zero. /// with all but the least significant bit set to zero.
unsigned FastEmitZExtFromI1(MVT VT, unsigned FastEmitZExtFromI1(MVT VT,
unsigned Op); unsigned Op0, bool Op0IsKill);
/// FastEmitBranch - Emit an unconditional branch to the given block, /// FastEmitBranch - Emit an unconditional branch to the given block,
/// unless it is the immediate (fall-through) successor, and update /// unless it is the immediate (fall-through) successor, and update
@ -317,6 +329,9 @@ private:
/// called when the value isn't already available in a register and must /// called when the value isn't already available in a register and must
/// be materialized with new instructions. /// be materialized with new instructions.
unsigned materializeRegForValue(const Value *V, MVT VT); unsigned materializeRegForValue(const Value *V, MVT VT);
/// hasTrivialKill - Test whether the given value has exactly one use.
bool hasTrivialKill(const Value *V) const;
}; };
} }

View File

@ -56,6 +56,12 @@
#include "FunctionLoweringInfo.h" #include "FunctionLoweringInfo.h"
using namespace llvm; using namespace llvm;
bool FastISel::hasTrivialKill(const Value *V) const {
// Don't consider constants or arguments to have trivial kills.
const Instruction *I = dyn_cast<Instruction>(V);
return I && I->hasOneUse();
}
unsigned FastISel::getRegForValue(const Value *V) { unsigned FastISel::getRegForValue(const Value *V) {
EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true); EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true);
// Don't handle non-simple values in FastISel. // Don't handle non-simple values in FastISel.
@ -134,7 +140,8 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
unsigned IntegerReg = unsigned IntegerReg =
getRegForValue(ConstantInt::get(V->getContext(), IntVal)); getRegForValue(ConstantInt::get(V->getContext(), IntVal));
if (IntegerReg != 0) if (IntegerReg != 0)
Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg); Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP,
IntegerReg, /*Kill=*/false);
} }
} }
} else if (const Operator *Op = dyn_cast<Operator>(V)) { } else if (const Operator *Op = dyn_cast<Operator>(V)) {
@ -190,20 +197,28 @@ unsigned FastISel::UpdateValueMap(const Value *I, unsigned Reg) {
return AssignedReg; return AssignedReg;
} }
unsigned FastISel::getRegForGEPIndex(const Value *Idx) { std::pair<unsigned, bool> FastISel::getRegForGEPIndex(const Value *Idx) {
unsigned IdxN = getRegForValue(Idx); unsigned IdxN = getRegForValue(Idx);
if (IdxN == 0) if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return 0; return std::pair<unsigned, bool>(0, false);
bool IdxNIsKill = hasTrivialKill(Idx);
// If the index is smaller or larger than intptr_t, truncate or extend it. // If the index is smaller or larger than intptr_t, truncate or extend it.
MVT PtrVT = TLI.getPointerTy(); MVT PtrVT = TLI.getPointerTy();
EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
if (IdxVT.bitsLT(PtrVT)) if (IdxVT.bitsLT(PtrVT)) {
IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, IdxN); IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND,
else if (IdxVT.bitsGT(PtrVT)) IdxN, IdxNIsKill);
IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, IdxN); IdxNIsKill = true;
return IdxN; }
else if (IdxVT.bitsGT(PtrVT)) {
IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE,
IdxN, IdxNIsKill);
IdxNIsKill = true;
}
return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
} }
/// SelectBinaryOp - Select and emit code for a binary operator instruction, /// SelectBinaryOp - Select and emit code for a binary operator instruction,
@ -235,10 +250,13 @@ bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) {
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
bool Op0IsKill = hasTrivialKill(I->getOperand(0));
// Check if the second operand is a constant and handle it appropriately. // Check if the second operand is a constant and handle it appropriately.
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(), unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(),
ISDOpcode, Op0, CI->getZExtValue()); ISDOpcode, Op0, Op0IsKill,
CI->getZExtValue());
if (ResultReg != 0) { if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction. // We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg); UpdateValueMap(I, ResultReg);
@ -249,7 +267,7 @@ bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) {
// Check if the second operand is a constant float. // Check if the second operand is a constant float.
if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) { if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(), unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(),
ISDOpcode, Op0, CF); ISDOpcode, Op0, Op0IsKill, CF);
if (ResultReg != 0) { if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction. // We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg); UpdateValueMap(I, ResultReg);
@ -262,9 +280,13 @@ bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) {
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
bool Op1IsKill = hasTrivialKill(I->getOperand(1));
// Now we have both operands in registers. Emit the instruction. // Now we have both operands in registers. Emit the instruction.
unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(), unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(),
ISDOpcode, Op0, Op1); ISDOpcode,
Op0, Op0IsKill,
Op1, Op1IsKill);
if (ResultReg == 0) if (ResultReg == 0)
// Target-specific code wasn't able to find a machine opcode for // Target-specific code wasn't able to find a machine opcode for
// the given ISD opcode and type. Halt "fast" selection and bail. // the given ISD opcode and type. Halt "fast" selection and bail.
@ -281,6 +303,8 @@ bool FastISel::SelectGetElementPtr(const User *I) {
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
bool NIsKill = hasTrivialKill(I->getOperand(0));
const Type *Ty = I->getOperand(0)->getType(); const Type *Ty = I->getOperand(0)->getType();
MVT VT = TLI.getPointerTy(); MVT VT = TLI.getPointerTy();
for (GetElementPtrInst::const_op_iterator OI = I->op_begin()+1, for (GetElementPtrInst::const_op_iterator OI = I->op_begin()+1,
@ -293,10 +317,11 @@ bool FastISel::SelectGetElementPtr(const User *I) {
uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field); uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field);
// FIXME: This can be optimized by combining the add with a // FIXME: This can be optimized by combining the add with a
// subsequent one. // subsequent one.
N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT); N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT);
if (N == 0) if (N == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
NIsKill = true;
} }
Ty = StTy->getElementType(Field); Ty = StTy->getElementType(Field);
} else { } else {
@ -307,27 +332,31 @@ bool FastISel::SelectGetElementPtr(const User *I) {
if (CI->getZExtValue() == 0) continue; if (CI->getZExtValue() == 0) continue;
uint64_t Offs = uint64_t Offs =
TD.getTypeAllocSize(Ty)*cast<ConstantInt>(CI)->getSExtValue(); TD.getTypeAllocSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT); N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT);
if (N == 0) if (N == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
NIsKill = true;
continue; continue;
} }
// N = N + Idx * ElementSize; // N = N + Idx * ElementSize;
uint64_t ElementSize = TD.getTypeAllocSize(Ty); uint64_t ElementSize = TD.getTypeAllocSize(Ty);
unsigned IdxN = getRegForGEPIndex(Idx); std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
unsigned IdxN = Pair.first;
bool IdxNIsKill = Pair.second;
if (IdxN == 0) if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
if (ElementSize != 1) { if (ElementSize != 1) {
IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, ElementSize, VT); IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, IdxNIsKill, ElementSize, VT);
if (IdxN == 0) if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
IdxNIsKill = true;
} }
N = FastEmit_rr(VT, VT, ISD::ADD, N, IdxN); N = FastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
if (N == 0) if (N == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
@ -447,13 +476,15 @@ bool FastISel::SelectCall(const User *I) {
assert(InsertedCopy && "Can't copy address registers!"); assert(InsertedCopy && "Can't copy address registers!");
InsertedCopy = InsertedCopy; InsertedCopy = InsertedCopy;
bool ResultRegIsKill = hasTrivialKill(I);
// Cast the register to the type of the selector. // Cast the register to the type of the selector.
if (SrcVT.bitsGT(MVT::i32)) if (SrcVT.bitsGT(MVT::i32))
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE,
ResultReg); ResultReg, ResultRegIsKill);
else if (SrcVT.bitsLT(MVT::i32)) else if (SrcVT.bitsLT(MVT::i32))
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32,
ISD::SIGN_EXTEND, ResultReg); ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill);
if (ResultReg == 0) if (ResultReg == 0)
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
@ -501,12 +532,15 @@ bool FastISel::SelectCast(const User *I, unsigned Opcode) {
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
bool InputRegIsKill = hasTrivialKill(I->getOperand(0));
// If the operand is i1, arrange for the high bits in the register to be zero. // If the operand is i1, arrange for the high bits in the register to be zero.
if (SrcVT == MVT::i1) { if (SrcVT == MVT::i1) {
SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT); SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT);
InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg); InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg, InputRegIsKill);
if (!InputReg) if (!InputReg)
return false; return false;
InputRegIsKill = true;
} }
// If the result is i1, truncate to the target's type for i1 first. // If the result is i1, truncate to the target's type for i1 first.
if (DstVT == MVT::i1) if (DstVT == MVT::i1)
@ -515,7 +549,7 @@ bool FastISel::SelectCast(const User *I, unsigned Opcode) {
unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(), unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(),
DstVT.getSimpleVT(), DstVT.getSimpleVT(),
Opcode, Opcode,
InputReg); InputReg, InputRegIsKill);
if (!ResultReg) if (!ResultReg)
return false; return false;
@ -548,6 +582,8 @@ bool FastISel::SelectBitCast(const User *I) {
// Unhandled operand. Halt "fast" selection and bail. // Unhandled operand. Halt "fast" selection and bail.
return false; return false;
bool Op0IsKill = hasTrivialKill(I->getOperand(0));
// First, try to perform the bitcast by inserting a reg-reg copy. // First, try to perform the bitcast by inserting a reg-reg copy.
unsigned ResultReg = 0; unsigned ResultReg = 0;
if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) { if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
@ -564,7 +600,7 @@ bool FastISel::SelectBitCast(const User *I) {
// If the reg-reg copy failed, select a BIT_CONVERT opcode. // If the reg-reg copy failed, select a BIT_CONVERT opcode.
if (!ResultReg) if (!ResultReg)
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(),
ISD::BIT_CONVERT, Op0); ISD::BIT_CONVERT, Op0, Op0IsKill);
if (!ResultReg) if (!ResultReg)
return false; return false;
@ -620,10 +656,12 @@ FastISel::SelectFNeg(const User *I) {
unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I)); unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I));
if (OpReg == 0) return false; if (OpReg == 0) return false;
bool OpRegIsKill = hasTrivialKill(I);
// If the target has ISD::FNEG, use it. // If the target has ISD::FNEG, use it.
EVT VT = TLI.getValueType(I->getType()); EVT VT = TLI.getValueType(I->getType());
unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(), unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(),
ISD::FNEG, OpReg); ISD::FNEG, OpReg, OpRegIsKill);
if (ResultReg != 0) { if (ResultReg != 0) {
UpdateValueMap(I, ResultReg); UpdateValueMap(I, ResultReg);
return true; return true;
@ -637,18 +675,19 @@ FastISel::SelectFNeg(const User *I) {
return false; return false;
unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(), unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(),
ISD::BIT_CONVERT, OpReg); ISD::BIT_CONVERT, OpReg, OpRegIsKill);
if (IntReg == 0) if (IntReg == 0)
return false; return false;
unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR, IntReg, unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR,
IntReg, /*Kill=*/true,
UINT64_C(1) << (VT.getSizeInBits()-1), UINT64_C(1) << (VT.getSizeInBits()-1),
IntVT.getSimpleVT()); IntVT.getSimpleVT());
if (IntResultReg == 0) if (IntResultReg == 0)
return false; return false;
ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(), ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(),
ISD::BIT_CONVERT, IntResultReg); ISD::BIT_CONVERT, IntResultReg, /*Kill=*/true);
if (ResultReg == 0) if (ResultReg == 0)
return false; return false;
@ -805,13 +844,15 @@ unsigned FastISel::FastEmit_(MVT, MVT,
} }
unsigned FastISel::FastEmit_r(MVT, MVT, unsigned FastISel::FastEmit_r(MVT, MVT,
unsigned, unsigned /*Op0*/) { unsigned,
unsigned /*Op0*/, bool /*Op0IsKill*/) {
return 0; return 0;
} }
unsigned FastISel::FastEmit_rr(MVT, MVT, unsigned FastISel::FastEmit_rr(MVT, MVT,
unsigned, unsigned /*Op0*/, unsigned,
unsigned /*Op0*/) { unsigned /*Op0*/, bool /*Op0IsKill*/,
unsigned /*Op1*/, bool /*Op1IsKill*/) {
return 0; return 0;
} }
@ -825,20 +866,23 @@ unsigned FastISel::FastEmit_f(MVT, MVT,
} }
unsigned FastISel::FastEmit_ri(MVT, MVT, unsigned FastISel::FastEmit_ri(MVT, MVT,
unsigned, unsigned /*Op0*/, unsigned,
unsigned /*Op0*/, bool /*Op0IsKill*/,
uint64_t /*Imm*/) { uint64_t /*Imm*/) {
return 0; return 0;
} }
unsigned FastISel::FastEmit_rf(MVT, MVT, unsigned FastISel::FastEmit_rf(MVT, MVT,
unsigned, unsigned /*Op0*/, unsigned,
unsigned /*Op0*/, bool /*Op0IsKill*/,
const ConstantFP * /*FPImm*/) { const ConstantFP * /*FPImm*/) {
return 0; return 0;
} }
unsigned FastISel::FastEmit_rri(MVT, MVT, unsigned FastISel::FastEmit_rri(MVT, MVT,
unsigned, unsigned,
unsigned /*Op0*/, unsigned /*Op1*/, unsigned /*Op0*/, bool /*Op0IsKill*/,
unsigned /*Op1*/, bool /*Op1IsKill*/,
uint64_t /*Imm*/) { uint64_t /*Imm*/) {
return 0; return 0;
} }
@ -848,16 +892,18 @@ unsigned FastISel::FastEmit_rri(MVT, MVT,
/// If that fails, it materializes the immediate into a register and try /// If that fails, it materializes the immediate into a register and try
/// FastEmit_rr instead. /// FastEmit_rr instead.
unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode, unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode,
unsigned Op0, uint64_t Imm, unsigned Op0, bool Op0IsKill,
MVT ImmType) { uint64_t Imm, MVT ImmType) {
// First check if immediate type is legal. If not, we can't use the ri form. // First check if immediate type is legal. If not, we can't use the ri form.
unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Imm); unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm);
if (ResultReg != 0) if (ResultReg != 0)
return ResultReg; return ResultReg;
unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm); unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm);
if (MaterialReg == 0) if (MaterialReg == 0)
return 0; return 0;
return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg); return FastEmit_rr(VT, VT, Opcode,
Op0, Op0IsKill,
MaterialReg, /*Kill=*/true);
} }
/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries /// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries
@ -865,10 +911,10 @@ unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode,
/// FastEmit_rf. If that fails, it materializes the immediate into a register /// FastEmit_rf. If that fails, it materializes the immediate into a register
/// and try FastEmit_rr instead. /// and try FastEmit_rr instead.
unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode, unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode,
unsigned Op0, const ConstantFP *FPImm, unsigned Op0, bool Op0IsKill,
MVT ImmType) { const ConstantFP *FPImm, MVT ImmType) {
// First check if immediate type is legal. If not, we can't use the rf form. // First check if immediate type is legal. If not, we can't use the rf form.
unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, FPImm); unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm);
if (ResultReg != 0) if (ResultReg != 0)
return ResultReg; return ResultReg;
@ -898,11 +944,13 @@ unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode,
if (IntegerReg == 0) if (IntegerReg == 0)
return 0; return 0;
MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT,
ISD::SINT_TO_FP, IntegerReg); ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true);
if (MaterialReg == 0) if (MaterialReg == 0)
return 0; return 0;
} }
return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg); return FastEmit_rr(VT, VT, Opcode,
Op0, Op0IsKill,
MaterialReg, /*Kill=*/true);
} }
unsigned FastISel::createResultReg(const TargetRegisterClass* RC) { unsigned FastISel::createResultReg(const TargetRegisterClass* RC) {
@ -920,14 +968,14 @@ unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode,
unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode, unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0) { unsigned Op0, bool Op0IsKill) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode); const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0); BuildMI(MBB, DL, II, ResultReg).addReg(Op0, Op0IsKill * RegState::Kill);
else { else {
BuildMI(MBB, DL, II).addReg(Op0); BuildMI(MBB, DL, II).addReg(Op0, Op0IsKill * RegState::Kill);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -939,14 +987,19 @@ unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode, unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, unsigned Op1) { unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode); const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1); BuildMI(MBB, DL, II, ResultReg)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addReg(Op1, Op1IsKill * RegState::Kill);
else { else {
BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1); BuildMI(MBB, DL, II)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addReg(Op1, Op1IsKill * RegState::Kill);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -957,14 +1010,19 @@ unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode, unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, uint64_t Imm) { unsigned Op0, bool Op0IsKill,
uint64_t Imm) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode); const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Imm); BuildMI(MBB, DL, II, ResultReg)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addImm(Imm);
else { else {
BuildMI(MBB, DL, II).addReg(Op0).addImm(Imm); BuildMI(MBB, DL, II)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addImm(Imm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -975,14 +1033,19 @@ unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode, unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, const ConstantFP *FPImm) { unsigned Op0, bool Op0IsKill,
const ConstantFP *FPImm) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode); const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addFPImm(FPImm); BuildMI(MBB, DL, II, ResultReg)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addFPImm(FPImm);
else { else {
BuildMI(MBB, DL, II).addReg(Op0).addFPImm(FPImm); BuildMI(MBB, DL, II)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addFPImm(FPImm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -993,14 +1056,22 @@ unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode, unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
unsigned Op0, unsigned Op1, uint64_t Imm) { unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode); const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1).addImm(Imm); BuildMI(MBB, DL, II, ResultReg)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addReg(Op1, Op1IsKill * RegState::Kill)
.addImm(Imm);
else { else {
BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1).addImm(Imm); BuildMI(MBB, DL, II)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addReg(Op1, Op1IsKill * RegState::Kill)
.addImm(Imm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -1028,16 +1099,21 @@ unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode,
} }
unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT, unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT,
unsigned Op0, uint32_t Idx) { unsigned Op0, bool Op0IsKill,
uint32_t Idx) {
const TargetRegisterClass* RC = MRI.getRegClass(Op0); const TargetRegisterClass* RC = MRI.getRegClass(Op0);
unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
const TargetInstrDesc &II = TII.get(TargetOpcode::EXTRACT_SUBREG); const TargetInstrDesc &II = TII.get(TargetOpcode::EXTRACT_SUBREG);
if (II.getNumDefs() >= 1) if (II.getNumDefs() >= 1)
BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Idx); BuildMI(MBB, DL, II, ResultReg)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addImm(Idx);
else { else {
BuildMI(MBB, DL, II).addReg(Op0).addImm(Idx); BuildMI(MBB, DL, II)
.addReg(Op0, Op0IsKill * RegState::Kill)
.addImm(Idx);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
II.ImplicitDefs[0], RC, RC, DL); II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy) if (!InsertedCopy)
@ -1048,8 +1124,8 @@ unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT,
/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op
/// with all but the least significant bit set to zero. /// with all but the least significant bit set to zero.
unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op) { unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill) {
return FastEmit_ri(VT, VT, ISD::AND, Op, 1); return FastEmit_ri(VT, VT, ISD::AND, Op0, Op0IsKill, 1);
} }
/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.

View File

@ -324,7 +324,8 @@ bool X86FastISel::X86FastEmitStore(EVT VT, const Value *Val,
bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT,
unsigned Src, EVT SrcVT, unsigned Src, EVT SrcVT,
unsigned &ResultReg) { unsigned &ResultReg) {
unsigned RR = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opc, Src); unsigned RR = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opc,
Src, /*TODO: Kill=*/false);
if (RR != 0) { if (RR != 0) {
ResultReg = RR; ResultReg = RR;
@ -416,7 +417,7 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
(S == 1 || S == 2 || S == 4 || S == 8)) { (S == 1 || S == 2 || S == 4 || S == 8)) {
// Scaled-index addressing. // Scaled-index addressing.
Scale = S; Scale = S;
IndexReg = getRegForGEPIndex(Op); IndexReg = getRegForGEPIndex(Op).first;
if (IndexReg == 0) if (IndexReg == 0)
return false; return false;
} else } else
@ -802,7 +803,7 @@ bool X86FastISel::X86SelectZExt(const Instruction *I) {
unsigned ResultReg = getRegForValue(I->getOperand(0)); unsigned ResultReg = getRegForValue(I->getOperand(0));
if (ResultReg == 0) return false; if (ResultReg == 0) return false;
// Set the high bits to zero. // Set the high bits to zero.
ResultReg = FastEmitZExtFromI1(MVT::i8, ResultReg); ResultReg = FastEmitZExtFromI1(MVT::i8, ResultReg, /*TODO: Kill=*/false);
if (ResultReg == 0) return false; if (ResultReg == 0) return false;
UpdateValueMap(I, ResultReg); UpdateValueMap(I, ResultReg);
return true; return true;
@ -1133,7 +1134,8 @@ bool X86FastISel::X86SelectTrunc(const Instruction *I) {
// Then issue an extract_subreg. // Then issue an extract_subreg.
unsigned ResultReg = FastEmitInst_extractsubreg(MVT::i8, unsigned ResultReg = FastEmitInst_extractsubreg(MVT::i8,
CopyReg, X86::SUBREG_8BIT); CopyReg, /*Kill=*/true,
X86::SUBREG_8BIT);
if (!ResultReg) if (!ResultReg)
return false; return false;
@ -1436,7 +1438,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
} }
case CCValAssign::BCvt: { case CCValAssign::BCvt: {
unsigned BC = FastEmit_r(ArgVT.getSimpleVT(), VA.getLocVT().getSimpleVT(), unsigned BC = FastEmit_r(ArgVT.getSimpleVT(), VA.getLocVT().getSimpleVT(),
ISD::BIT_CONVERT, Arg); ISD::BIT_CONVERT, Arg, /*TODO: Kill=*/false);
assert(BC != 0 && "Failed to emit a bitcast!"); assert(BC != 0 && "Failed to emit a bitcast!");
Arg = BC; Arg = BC;
ArgVT = VA.getLocVT(); ArgVT = VA.getLocVT();

View File

@ -123,7 +123,7 @@ struct OperandsSignature {
void PrintParameters(raw_ostream &OS) const { void PrintParameters(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) { for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] == "r") { if (Operands[i] == "r") {
OS << "unsigned Op" << i; OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
} else if (Operands[i] == "i") { } else if (Operands[i] == "i") {
OS << "uint64_t imm" << i; OS << "uint64_t imm" << i;
} else if (Operands[i] == "f") { } else if (Operands[i] == "f") {
@ -149,7 +149,7 @@ struct OperandsSignature {
if (PrintedArg) if (PrintedArg)
OS << ", "; OS << ", ";
if (Operands[i] == "r") { if (Operands[i] == "r") {
OS << "Op" << i; OS << "Op" << i << ", Op" << i << "IsKill";
PrintedArg = true; PrintedArg = true;
} else if (Operands[i] == "i") { } else if (Operands[i] == "i") {
OS << "imm" << i; OS << "imm" << i;
@ -167,7 +167,7 @@ struct OperandsSignature {
void PrintArguments(raw_ostream &OS) const { void PrintArguments(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) { for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] == "r") { if (Operands[i] == "r") {
OS << "Op" << i; OS << "Op" << i << ", Op" << i << "IsKill";
} else if (Operands[i] == "i") { } else if (Operands[i] == "i") {
OS << "imm" << i; OS << "imm" << i;
} else if (Operands[i] == "f") { } else if (Operands[i] == "f") {
@ -447,7 +447,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
OS << ");\n"; OS << ");\n";
} else { } else {
OS << "extractsubreg(" << getName(RetVT); OS << "extractsubreg(" << getName(RetVT);
OS << ", Op0, "; OS << ", Op0, Op0IsKill, ";
OS << (unsigned)Memo.SubRegNo; OS << (unsigned)Memo.SubRegNo;
OS << ");\n"; OS << ");\n";
} }
@ -541,7 +541,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
Operands.PrintArguments(OS, *Memo.PhysRegs); Operands.PrintArguments(OS, *Memo.PhysRegs);
OS << ");\n"; OS << ");\n";
} else { } else {
OS << "extractsubreg(RetVT, Op0, "; OS << "extractsubreg(RetVT, Op0, Op0IsKill, ";
OS << (unsigned)Memo.SubRegNo; OS << (unsigned)Memo.SubRegNo;
OS << ");\n"; OS << ");\n";
} }