LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 861 - ret i64 doesn't work on 16-bit targets
Summary: ret i64 doesn't work on 16-bit targets
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Common Code Generator Code (show other bugs)
Version: trunk
Hardware: All All
: P normal
Assignee: Chris Lattner
URL:
Keywords: compile-fail
Depends on:
Blocks:
 
Reported: 2006-08-01 09:59 PDT by Duraid Madina
Modified: 2010-02-22 12:43 PST (History)
1 user (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Duraid Madina 2006-08-01 09:59:02 PDT
on a target with only i16 registers, the following code:

ulong %foo() { ret ulong 31189350395091 }

asserts in legalization: instead of being legalized down to 4xi16, it gets
turned into 2xi32 and then trips over an assert (LegalizeDAG.cpp:1458, "Register
type must be legal!") - the code there seems to assume that if an integer isn't
legal, one "break up" into two smaller regs is sufficient to make it so. This is
true for any target with i32 regs since i64 is the biggest we have, but if even
i32 isn't legal for a target, further legalization is required.
Comment 1 Chris Lattner 2006-08-01 11:13:17 PDT
The code generator is built to allow recursive expansion (expand i64 -> 2xi32 then each i32 -> 2x i16).  
Unfortunately, without a 16 bit target to test on, I'm sure there are missing cases.  In particular, some 
specific pieces of code (e.g. CopyToReg insertion?) may not be aware that expanding once may not be 
enough.

If you track down the specific cases that don't work, we can get them fixed.  What is the stack trace for 
this failure?

-Chris

Comment 2 Duraid Madina 2006-08-01 17:55:25 PDT
The stack trace:

#3  0x086e9d66 in (anonymous namespace)::SelectionDAGLegalize::LegalizeOp
(this=0xbf955350, Op={Val = 0x8a55470, ResNo = 0})
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1458
#4  0x086e9c84 in (anonymous namespace)::SelectionDAGLegalize::LegalizeOp
(this=0xbf955350, Op={Val = 0x8a55500, ResNo = 0})
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1456
#5  0x086e160e in (anonymous namespace)::SelectionDAGLegalize::LegalizeOp
(this=0xbf955350, Op={Val = 0x8a55718, ResNo = 0})
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:546
#6  0x086f67b7 in (anonymous namespace)::SelectionDAGLegalize::LegalizeOp
(this=0xbf955350, Op={Val = 0x8a55230, ResNo = 0})
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:2854
#7  0x08704dd9 in (anonymous namespace)::SelectionDAGLegalize::HandleOp
(this=0xbf955350, Op={Val = 0x8a55230, ResNo = 0})
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:458
#8  0x087053f2 in (anonymous namespace)::SelectionDAGLegalize::LegalizeDAG
(this=0xbf955350)
    at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:338
#9  0x08705582 in llvm::SelectionDAG::Legalize (this=0xbf9556e4) at
/home/duraid/strategist/compiler/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:4980

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

and here's a bit of the DAG at that point:

  0x8a552c8: i32 = Constant <3592858835>
  0x8a55328: i32 = Constant <7261>
    0x8a54fd8: <multiple use>
    0x8a54fd8: <multiple use>
  0x8a553e8: ch = TokenFactor 0x8a54fd8, 0x8a54fd8
    0x8a553e8: <multiple use>
    0x8a555e8: i32 = Register  r8
    0x8a552c8: <multiple use>
  0x8a55470: ch,flag = CopyToReg 0x8a553e8, 0x8a555e8, 0x8a552c8

Comment 3 Chris Lattner 2006-08-17 16:48:33 PDT
Okay, the problem is that the dag is bogus.  Can you find out what is making the i32 copytoreg nodes?  
SelectionDAGISel should only produce legal width copytoreg's.  It's probably the generic lowerret code or 
your target-specific one.

-Chris
Comment 4 Duraid Madina 2006-08-19 05:48:32 PDT
OK, I thought it might be my custom RET lowering code at fault, but now I'm not
so sure. The problem is, I'm switching on the number of operands the RET has:
1/3/5/7 for ret void/i16/i32/i64. It turns out that it's never even getting to
the i64 branch: the ret has 5 operands whether or not it's returning i32 or i64.

So I guess the bug is in the generic RET legalize code? Those i32 copytoreg
nodes are coming from the 5-operand path in my custom RET lowering code, which
is just:

MVT::ValueType ArgVT = Op.getOperand(1).getValueType();
assert(MVT::isInteger(ArgVT) && "no FP here buddy");
Copy = DAG.getCopyToReg(Op.getOperand(0), Strategist::r8, Op.getOperand(1),
SDOperand());
Copy = DAG.getCopyToReg(Copy,             Strategist::r9, Op.getOperand(3),
Copy.getValue(1));
return DAG.getNode(StrategistISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
Comment 5 Duraid Madina 2006-08-19 05:51:24 PDT
err, I meant 1/3/5/9 of course, not 1/3/5/7.
Comment 6 Chris Lattner 2006-08-21 15:25:53 PDT
This should fix the ret i64 case, lemme know if it doesn't.

http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20060821/036913.html

-Chris