[PowerPC, RFC] Wrong-code bug in pre-inc creation
Hal Finkel
hfinkel at anl.gov
Wed May 15 06:48:14 PDT 2013
----- Original Message -----
>
> Hi Hal,
>
> running the test-suite in 32-bit mode I ran into a crash which turns
> out to
> be caused by wrong code generated by the pre-inc matcher. In theory
> this
> ought to be triggerable in 64-bit mode as well, but I haven't found a
> test
> case yet. The 32-bit test case is generated (via the vectorizer)
> from a
> loop along the lines of:
>
> void test(int lo, int hi, double p[])
> {
> for (int j = hi; j > lo; j--)
> p[j] = 0;
> }
>
> The minimal 32-bit test case is (extracted from the vectorized and
> then
> unrolled loop):
>
> target datalayout =
> "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32"
> target triple = "powerpc-unknown-linux-gnu"
>
> define void @test(double* nocapture %p) {
> entry:
> %p1 = bitcast double* %p to <2 x double>*
> store <2 x double> zeroinitializer, <2 x double>* %p1, align 8
> %p2 = getelementptr <2 x double>* %p1, i32 -1
> store <2 x double> zeroinitializer, <2 x double>* %p2, align 8
> ret void
> }
>
> which gets compiled to:
>
> test:
> li 4, 0
> mr 5, 3
> stwu 4, 8(5)
> stw 4, 4(3)
> stw 4, 0(3)
> stw 4, 4(5)
> lis 5, -1
> stwu 4, -16(3)
> ori 6, 5, 12
> ori 5, 5, 8
> stwx 4, 3, 6
> stwx 4, 3, 5
> stw 4, 4(3)
> blr
>
> Note the obviously bogus offsets in registers 5 and 6.
>
>
> It turns out the problem originates with
> PPCTargetLowering::getPreIndexedAddressParts. This routine calls
> SelectAddressRegImm to extract the base and displacement parts.
> However,
> the displacement is translated into a TargetConstant by code like:
>
> if (isIntS16Immediate(N.getOperand(1), imm)) {
> Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32);
>
> Note how e.g. a displacement of -8 results in a displacement
> TargetConstant
> of type i32 and value 65528. This doesn't much matter for code
> generation, as it is implicitly treated as a 16-bit signed value
> there.
> However, on return from getPreIndexedAddressParts, the code in
> DAGCombiner::CombineToPreIndexedLoadStore looks at the displacement
> value
> returned by target code and interprets it as the actual displacement,
> so it
> thinks after the pre-inc instruction, the base register will actually
> have
> been *incremented* by 65528 instead of decremented by 8. It
> therefore
> changes the subsequent users of the base register to account for that
> supposed increment ...
>
> By inspection, it would appear that for 64-bit the problem might be
> even
> worse, since the "displacement" returned by SelectAddressRegImmShift
> is
> actually the displacement divided by 4, but again common DAGCombiner
> code
> would treat this value as the displacement itself. I've not yet
> attempted
> to construct a test case showing this issue.
>
>
> Now the question is how to best fix this. And this in turn leads me
> to
> wonder why the code does it this way in the first place. It would
> appear
> more natural to me to have the displacement MI operand represent the
> actual
> displacement in all cases, i.e. not force it to an unsigned 16-bit
> value
> for 32-bit, and neither divide it by 4 for 64-bit (but simply ensure
> proper
> alignment). However, this code basically did it that way since the
> very
> beginning, so I was wondering whether there was a reason for this
> that I
> may not be seeing ...
>
> Any thoughts on this?
I think that this is the right thing to do. Thanks!
I had some impression that things are as they are because that way the constants are setup for the built-in assembler (but given that they values would just be sign extended, I don't know if that matters anyway).
-Hal
> I'll try to come up with a patch that
> implements
> changes along those lines and see what falls out.
>
>
> Bye,
> Ulrich
>
>
More information about the llvm-commits
mailing list