mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
x32. Fixes jmp %reg in x32
x32 has 32-bit pointers; x86-64 can't jmp %r32. This patch addresses this issue by explicitly zero-extending brind's target to 64-bits. Author: jpp Reviewers: jfb, dschuff, pavel.v.chupin Subscribers: llvm-commits Differential revision: http://reviews.llvm.org/D12112 llvm-svn: 245452
This commit is contained in:
parent
ae28c8d3da
commit
3ff38c2bd2
@ -2224,6 +2224,27 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
|
||||
|
||||
switch (Opcode) {
|
||||
default: break;
|
||||
case ISD::BRIND: {
|
||||
if (Subtarget->isTargetNaCl())
|
||||
// NaCl has its own pass where jmp %r32 are converted to jmp %r64. We
|
||||
// leave the instruction alone.
|
||||
break;
|
||||
if (Subtarget->isTarget64BitILP32()) {
|
||||
// Converts a 32-bit register to a 64-bit, zero-extended version of
|
||||
// it. This is needed because x86-64 can do many things, but jmp %r32
|
||||
// ain't one of them.
|
||||
const SDValue &Target = Node->getOperand(1);
|
||||
assert(Target.getSimpleValueType() == llvm::MVT::i32);
|
||||
SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, EVT(MVT::i64));
|
||||
SDValue Brind = CurDAG->getNode(ISD::BRIND, dl, MVT::Other,
|
||||
Node->getOperand(0), ZextTarget);
|
||||
ReplaceUses(SDValue(Node, 0), Brind);
|
||||
SelectCode(ZextTarget.getNode());
|
||||
SelectCode(Brind.getNode());
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ISD::INTRINSIC_W_CHAIN: {
|
||||
unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
|
||||
switch (IntNo) {
|
||||
|
26
test/CodeGen/X86/x32-indirectbr.ll
Normal file
26
test/CodeGen/X86/x32-indirectbr.ll
Normal file
@ -0,0 +1,26 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-none-none-gnux32 -mcpu=generic | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=x86_64-none-none-gnux32 -mcpu=generic -fast-isel | FileCheck %s
|
||||
; Bug 22859
|
||||
;
|
||||
; x32 pointers are 32-bits wide. x86-64 indirect branches use the full 64-bit
|
||||
; registers. Therefore, x32 CodeGen needs to zero extend indirectbr's target to
|
||||
; 64-bit.
|
||||
|
||||
define i8 @test1() nounwind ssp {
|
||||
entry:
|
||||
%0 = select i1 undef, ; <i8*> [#uses=1]
|
||||
i8* blockaddress(@test1, %bb),
|
||||
i8* blockaddress(@test1, %bb6)
|
||||
indirectbr i8* %0, [label %bb, label %bb6]
|
||||
bb: ; preds = %entry
|
||||
ret i8 1
|
||||
|
||||
bb6: ; preds = %entry
|
||||
ret i8 2
|
||||
}
|
||||
; CHECK-LABEL: @test1
|
||||
; We are looking for a movl ???, %r32 followed by a 64-bit jmp through the
|
||||
; same register.
|
||||
; CHECK: movl {{.*}}, %{{e|r}}[[REG:.[^d]*]]{{d?}}
|
||||
; CHECK-NEXT: jmpq *%r[[REG]]
|
||||
|
Loading…
x
Reference in New Issue
Block a user