mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
Hexagon: Add support to generate predicated absolute addressing mode
instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174973 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5c97450df7
commit
6b8d2026ba
@ -2237,38 +2237,141 @@ PredicateInstruction(MachineInstr *MI,
|
||||
assert (isPredicable(MI) && "Expected predicable instruction");
|
||||
bool invertJump = (!Cond.empty() && Cond[0].isImm() &&
|
||||
(Cond[0].getImm() == 0));
|
||||
MI->setDesc(get(getMatchingCondBranchOpcode(Opc, invertJump)));
|
||||
//
|
||||
// This assumes that the predicate is always the first operand
|
||||
// in the set of inputs.
|
||||
//
|
||||
MI->addOperand(MI->getOperand(MI->getNumOperands()-1));
|
||||
int oper;
|
||||
for (oper = MI->getNumOperands() - 3; oper >= 0; --oper) {
|
||||
MachineOperand MO = MI->getOperand(oper);
|
||||
if ((MO.isReg() && !MO.isUse() && !MO.isImplicit())) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (MO.isReg()) {
|
||||
MI->getOperand(oper+1).ChangeToRegister(MO.getReg(), MO.isDef(),
|
||||
MO.isImplicit(), MO.isKill(),
|
||||
MO.isDead(), MO.isUndef(),
|
||||
MO.isDebug());
|
||||
} else if (MO.isImm()) {
|
||||
MI->getOperand(oper+1).ChangeToImmediate(MO.getImm());
|
||||
} else {
|
||||
llvm_unreachable("Unexpected operand type");
|
||||
// This will change MI's opcode to its predicate version.
|
||||
// However, its operand list is still the old one, i.e. the
|
||||
// non-predicate one.
|
||||
MI->setDesc(get(getMatchingCondBranchOpcode(Opc, invertJump)));
|
||||
|
||||
int oper = -1;
|
||||
unsigned int GAIdx = 0;
|
||||
|
||||
// Indicates whether the current MI has a GlobalAddress operand
|
||||
bool hasGAOpnd = false;
|
||||
std::vector<MachineOperand> tmpOpnds;
|
||||
|
||||
// Indicates whether we need to shift operands to right.
|
||||
bool needShift = true;
|
||||
|
||||
// The predicate is ALWAYS the FIRST input operand !!!
|
||||
if (MI->getNumOperands() == 0) {
|
||||
// The non-predicate version of MI does not take any operands,
|
||||
// i.e. no outs and no ins. In this condition, the predicate
|
||||
// operand will be directly placed at Operands[0]. No operand
|
||||
// shift is needed.
|
||||
// Example: BARRIER
|
||||
needShift = false;
|
||||
oper = -1;
|
||||
}
|
||||
else if ( MI->getOperand(MI->getNumOperands()-1).isReg()
|
||||
&& MI->getOperand(MI->getNumOperands()-1).isDef()
|
||||
&& !MI->getOperand(MI->getNumOperands()-1).isImplicit()) {
|
||||
// The non-predicate version of MI does not have any input operands.
|
||||
// In this condition, we extend the length of Operands[] by one and
|
||||
// copy the original last operand to the newly allocated slot.
|
||||
// At this moment, it is just a place holder. Later, we will put
|
||||
// predicate operand directly into it. No operand shift is needed.
|
||||
// Example: r0=BARRIER (this is a faked insn used here for illustration)
|
||||
MI->addOperand(MI->getOperand(MI->getNumOperands()-1));
|
||||
needShift = false;
|
||||
oper = MI->getNumOperands() - 2;
|
||||
}
|
||||
else {
|
||||
// We need to right shift all input operands by one. Duplicate the
|
||||
// last operand into the newly allocated slot.
|
||||
MI->addOperand(MI->getOperand(MI->getNumOperands()-1));
|
||||
}
|
||||
|
||||
if (needShift)
|
||||
{
|
||||
// Operands[ MI->getNumOperands() - 2 ] has been copied into
|
||||
// Operands[ MI->getNumOperands() - 1 ], so we start from
|
||||
// Operands[ MI->getNumOperands() - 3 ].
|
||||
// oper is a signed int.
|
||||
// It is ok if "MI->getNumOperands()-3" is -3, -2, or -1.
|
||||
for (oper = MI->getNumOperands() - 3; oper >= 0; --oper)
|
||||
{
|
||||
MachineOperand &MO = MI->getOperand(oper);
|
||||
|
||||
// Opnd[0] Opnd[1] Opnd[2] Opnd[3] Opnd[4] Opnd[5] Opnd[6] Opnd[7]
|
||||
// <Def0> <Def1> <Use0> <Use1> <ImpDef0> <ImpDef1> <ImpUse0> <ImpUse1>
|
||||
// /\~
|
||||
// /||\~
|
||||
// ||
|
||||
// Predicate Operand here
|
||||
if (MO.isReg() && !MO.isUse() && !MO.isImplicit()) {
|
||||
break;
|
||||
}
|
||||
if (MO.isReg()) {
|
||||
MI->getOperand(oper+1).ChangeToRegister(MO.getReg(), MO.isDef(),
|
||||
MO.isImplicit(), MO.isKill(),
|
||||
MO.isDead(), MO.isUndef(),
|
||||
MO.isDebug());
|
||||
}
|
||||
else if (MO.isImm()) {
|
||||
MI->getOperand(oper+1).ChangeToImmediate(MO.getImm());
|
||||
}
|
||||
else if (MO.isGlobal()) {
|
||||
// MI can not have more than one GlobalAddress operand.
|
||||
assert(hasGAOpnd == false && "MI can only have one GlobalAddress opnd");
|
||||
|
||||
// There is no member function called "ChangeToGlobalAddress" in the
|
||||
// MachineOperand class (not like "ChangeToRegister" and
|
||||
// "ChangeToImmediate"). So we have to remove them from Operands[] list
|
||||
// first, and then add them back after we have inserted the predicate
|
||||
// operand. tmpOpnds[] is to remember these operands before we remove
|
||||
// them.
|
||||
tmpOpnds.push_back(MO);
|
||||
|
||||
// Operands[oper] is a GlobalAddress operand;
|
||||
// Operands[oper+1] has been copied into Operands[oper+2];
|
||||
hasGAOpnd = true;
|
||||
GAIdx = oper;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
assert(false && "Unexpected operand type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int regPos = invertJump ? 1 : 0;
|
||||
MachineOperand PredMO = Cond[regPos];
|
||||
|
||||
// [oper] now points to the last explicit Def. Predicate operand must be
|
||||
// located at [oper+1]. See diagram above.
|
||||
// This assumes that the predicate is always the first operand,
|
||||
// i.e. Operands[0+numResults], in the set of inputs
|
||||
// It is better to have an assert here to check this. But I don't know how
|
||||
// to write this assert because findFirstPredOperandIdx() would return -1
|
||||
if (oper < -1) oper = -1;
|
||||
MI->getOperand(oper+1).ChangeToRegister(PredMO.getReg(), PredMO.isDef(),
|
||||
PredMO.isImplicit(), PredMO.isKill(),
|
||||
PredMO.isDead(), PredMO.isUndef(),
|
||||
PredMO.isDebug());
|
||||
|
||||
if (hasGAOpnd)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
// Operands[GAIdx] is the original GlobalAddress operand, which is
|
||||
// already copied into tmpOpnds[0].
|
||||
// Operands[GAIdx] now stores a copy of Operands[GAIdx-1]
|
||||
// Operands[GAIdx+1] has already been copied into Operands[GAIdx+2],
|
||||
// so we start from [GAIdx+2]
|
||||
for (i = GAIdx + 2; i < MI->getNumOperands(); ++i)
|
||||
tmpOpnds.push_back(MI->getOperand(i));
|
||||
|
||||
// Remove all operands in range [ (GAIdx+1) ... (MI->getNumOperands()-1) ]
|
||||
// It is very important that we always remove from the end of Operands[]
|
||||
// MI->getNumOperands() is at least 2 if program goes to here.
|
||||
for (i = MI->getNumOperands() - 1; i > GAIdx; --i)
|
||||
MI->RemoveOperand(i);
|
||||
|
||||
for (i = 0; i < tmpOpnds.size(); ++i)
|
||||
MI->addOperand(tmpOpnds[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
19
test/CodeGen/Hexagon/pred-absolute-store.ll
Normal file
19
test/CodeGen/Hexagon/pred-absolute-store.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; Check that we are able to predicate instructions with abosolute
|
||||
; addressing mode.
|
||||
|
||||
; CHECK: if{{ *}}(p{{[0-3]+}}){{ *}}memw(##gvar){{ *}}={{ *}}r{{[0-9]+}}
|
||||
|
||||
@gvar = external global i32
|
||||
define i32 @test2(i32 %a, i32 %b) nounwind {
|
||||
entry:
|
||||
%cmp = icmp eq i32 %a, %b
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
store i32 %a, i32* @gvar, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
ret i32 %b
|
||||
}
|
Loading…
Reference in New Issue
Block a user