Index: lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- lib/Target/X86/X86ISelDAGToDAG.cpp +++ lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2277,6 +2277,20 @@ switch (Opcode) { default: break; + case ISD::BRIND: { + if (Subtarget->isTarget64BitILP32() && !Subtarget->isTargetNaCl()) { + 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(Node->getOperand(1))->getZExtValue(); switch (IntNo) { Index: test/CodeGen/X86/x32-indirectbr.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/x32-indirectbr.ll @@ -0,0 +1,56 @@ +; 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, ; [#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: movl {{.*}}, %{{e|r}}[[REG:.[^d]*]]{{d?}} +; CHECK: jmpq *%r[[REG]] + +define i32 @test2(i32 %idx) nounwind ssp { +entry: + switch i32 %idx, label %abort [ + i32 0, label %idx0 + i32 1, label %idx1 + i32 2, label %idx2 + i32 3, label %idx3 + i32 4, label %idx4 + i32 5, label %idx5 + i32 6, label %idx6 + i32 7, label %idx7 + ] +idx0: ; preds = %entry + ret i32 55 +idx1: ; preds = %entry + ret i32 10 +idx2: ; preds = %entry + ret i32 -1 +idx3: ; preds = %entry + ret i32 1024 +idx4: ; preds = %entry + ret i32 -1024 +idx5: ; preds = %entry + ret i32 58 +idx6: ; preds = %entry + ret i32 30 +idx7: ; preds = %entry + ret i32 40 +abort: ; preds = %entry + unreachable +} +; CHECK: movl {{.*}}, %{{e|r}}[[REG:.[^d]*]]{{d?}} +; CHECK: jmpq *%r[[REG]]