[LLVMdev] Mips backend -- Incorrect globaladdr/constpool address generation when bit 15 of address is set?
Matt Johnson
johnso87 at crhc.illinois.edu
Wed Jun 22 15:48:01 PDT 2011
Hi All,
In SVN head, MipsISelDAGToDAG.cpp has the following optimization:
// Operand is a result from an ADD.
if (Addr.getOpcode() == ISD::ADD) {
// When loading from constant pools, load the lower address part in
// the instruction itself. Example, instead of:
// lui $2, %hi($CPI1_0)
// addiu $2, $2, %lo($CPI1_0)
// lwc1 $f0, 0($2)
// Generate:
// lui $2, %hi($CPI1_0)
// lwc1 $f0, %lo($CPI1_0)($2)
if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi ||
Addr.getOperand(0).getOpcode() == ISD::LOAD) &&
Addr.getOperand(1).getOpcode() == MipsISD::Lo) {
SDValue LoVal = Addr.getOperand(1);
if (dyn_cast<ConstantPoolSDNode>(LoVal.getOperand(0))) {
Base = Addr.getOperand(0);
Offset = LoVal.getOperand(0);
return true;
}
}
}
This optimization folds the low 16 bits of the global address into the
load offset,
rather than generating a separate 'addiu' instruction.
To my understanding, the offset fields in MIPS load instructions are
sign-extended,
not zero-extended, so this optimization will give the wrong answer if
%lo($CPI1_0)
is, for example, 0xFFFF, because the address computed will be (r2-1),
not (r2+65535).
It seems like you can only perform this optimization if you know the
absolute address
(which you won't until link time), and if bit 15 of the address happens
to be set,
you have to do some math to get the sign-extended offset to compute the
right thing
(essentially, you'd have to "lui $2, (%hi(CPI1_0)+1)").
Is this a bug?
Thanks,
Matt
More information about the llvm-dev
mailing list