diff options
-rw-r--r-- | lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp | 3 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 33 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.h | 1 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstr64Bit.td | 4 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.td | 4 | ||||
-rw-r--r-- | test/CodeGen/PowerPC/indirectbr.ll | 55 |
6 files changed, 100 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index 4bc58d215a..2dac18faa9 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -414,6 +414,9 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); return; + case MachineOperand::MO_BlockAddress: + GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); + return; case MachineOperand::MO_ExternalSymbol: { // Computing the address of an external symbol, not calling it. std::string Name(MAI->getGlobalPrefix()); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 3920b38150..7f48ef08f1 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -196,10 +196,12 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) // appropriate instructions to materialize the address. setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); setOperationAction(ISD::JumpTable, MVT::i32, Custom); setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); + setOperationAction(ISD::BlockAddress, MVT::i64, Custom); setOperationAction(ISD::ConstantPool, MVT::i64, Custom); setOperationAction(ISD::JumpTable, MVT::i64, Custom); @@ -1167,6 +1169,36 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, return SDValue(); // Not reached } +SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + DebugLoc DL = Op.getDebugLoc(); + + BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); + SDValue TgtBA = DAG.getBlockAddress(BA, DL, /*isTarget=*/true); + SDValue Zero = DAG.getConstant(0, PtrVT); + SDValue Hi = DAG.getNode(PPCISD::Hi, DL, PtrVT, TgtBA, Zero); + SDValue Lo = DAG.getNode(PPCISD::Lo, DL, PtrVT, TgtBA, Zero); + + // If this is a non-darwin platform, we don't support non-static relo models + // yet. + const TargetMachine &TM = DAG.getTarget(); + if (TM.getRelocationModel() == Reloc::Static || + !TM.getSubtarget<PPCSubtarget>().isDarwin()) { + // Generate non-pic code that has direct accesses to globals. + // The address of the global is just (hi(&g)+lo(&g)). + return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); + } + + if (TM.getRelocationModel() == Reloc::PIC_) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, DL, PtrVT, + DAG.getNode(PPCISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), PtrVT), Hi); + } + + return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); +} + SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { EVT PtrVT = Op.getValueType(); @@ -4181,6 +4213,7 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: llvm_unreachable("Wasn't expecting to be able to lower this!"); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index ac72d8765b..e45b261f15 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -361,6 +361,7 @@ namespace llvm { SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG); SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index d1e1bd5c1a..ebdc58b690 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -731,9 +731,13 @@ def : Pat<(PPChi tconstpool:$in , 0), (LIS8 tconstpool:$in)>; def : Pat<(PPClo tconstpool:$in , 0), (LI8 tconstpool:$in)>; def : Pat<(PPChi tjumptable:$in , 0), (LIS8 tjumptable:$in)>; def : Pat<(PPClo tjumptable:$in , 0), (LI8 tjumptable:$in)>; +def : Pat<(PPChi tblockaddress:$in, 0), (LIS8 tblockaddress:$in)>; +def : Pat<(PPClo tblockaddress:$in, 0), (LI8 tblockaddress:$in)>; def : Pat<(add G8RC:$in, (PPChi tglobaladdr:$g, 0)), (ADDIS8 G8RC:$in, tglobaladdr:$g)>; def : Pat<(add G8RC:$in, (PPChi tconstpool:$g, 0)), (ADDIS8 G8RC:$in, tconstpool:$g)>; def : Pat<(add G8RC:$in, (PPChi tjumptable:$g, 0)), (ADDIS8 G8RC:$in, tjumptable:$g)>; +def : Pat<(add G8RC:$in, (PPChi tblockaddress:$g, 0)), + (ADDIS8 G8RC:$in, tblockaddress:$g)>; diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 1c7c05e0c4..f5c095a3c7 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -1436,12 +1436,16 @@ def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>; def : Pat<(PPClo tconstpool:$in, 0), (LI tconstpool:$in)>; def : Pat<(PPChi tjumptable:$in, 0), (LIS tjumptable:$in)>; def : Pat<(PPClo tjumptable:$in, 0), (LI tjumptable:$in)>; +def : Pat<(PPChi tblockaddress:$in, 0), (LIS tblockaddress:$in)>; +def : Pat<(PPClo tblockaddress:$in, 0), (LI tblockaddress:$in)>; def : Pat<(add GPRC:$in, (PPChi tglobaladdr:$g, 0)), (ADDIS GPRC:$in, tglobaladdr:$g)>; def : Pat<(add GPRC:$in, (PPChi tconstpool:$g, 0)), (ADDIS GPRC:$in, tconstpool:$g)>; def : Pat<(add GPRC:$in, (PPChi tjumptable:$g, 0)), (ADDIS GPRC:$in, tjumptable:$g)>; +def : Pat<(add GPRC:$in, (PPChi tblockaddress:$g, 0)), + (ADDIS GPRC:$in, tblockaddress:$g)>; // Fused negative multiply subtract, alternate pattern def : Pat<(fsub F8RC:$B, (fmul F8RC:$A, F8RC:$C)), diff --git a/test/CodeGen/PowerPC/indirectbr.ll b/test/CodeGen/PowerPC/indirectbr.ll new file mode 100644 index 0000000000..94ad093154 --- /dev/null +++ b/test/CodeGen/PowerPC/indirectbr.ll @@ -0,0 +1,55 @@ +; RUN: llc < %s -relocation-model=pic -march=ppc32 | FileCheck %s -check-prefix=PIC +; RUN: llc < %s -relocation-model=static -march=ppc32 | FileCheck %s -check-prefix=STATIC + +@nextaddr = global i8* null ; <i8**> [#uses=2] +@C.0.2070 = private constant [5 x i8*] [i8* blockaddress(@foo, %L1), i8* blockaddress(@foo, %L2), i8* blockaddress(@foo, %L3), i8* blockaddress(@foo, %L4), i8* blockaddress(@foo, %L5)] ; <[5 x i8*]*> [#uses=1] + +define internal i32 @foo(i32 %i) nounwind { +; PIC: foo: +; STATIC: foo: +entry: + %0 = load i8** @nextaddr, align 4 ; <i8*> [#uses=2] + %1 = icmp eq i8* %0, null ; <i1> [#uses=1] + br i1 %1, label %bb3, label %bb2 + +bb2: ; preds = %entry, %bb3 + %gotovar.4.0 = phi i8* [ %gotovar.4.0.pre, %bb3 ], [ %0, %entry ] ; <i8*> [#uses=1] +; PIC: mtctr +; PIC-NEXT: bctr +; STATIC: mtctr +; STATIC-NEXT: bctr + indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1] + +bb3: ; preds = %entry + %2 = getelementptr inbounds [5 x i8*]* @C.0.2070, i32 0, i32 %i ; <i8**> [#uses=1] + %gotovar.4.0.pre = load i8** %2, align 4 ; <i8*> [#uses=1] + br label %bb2 + +L5: ; preds = %bb2 + br label %L4 + +L4: ; preds = %L5, %bb2 + %res.0 = phi i32 [ 385, %L5 ], [ 35, %bb2 ] ; <i32> [#uses=1] + br label %L3 + +L3: ; preds = %L4, %bb2 + %res.1 = phi i32 [ %res.0, %L4 ], [ 5, %bb2 ] ; <i32> [#uses=1] + br label %L2 + +L2: ; preds = %L3, %bb2 + %res.2 = phi i32 [ %res.1, %L3 ], [ 1, %bb2 ] ; <i32> [#uses=1] + %phitmp = mul i32 %res.2, 6 ; <i32> [#uses=1] + br label %L1 + +L1: ; preds = %L2, %bb2 + %res.3 = phi i32 [ %phitmp, %L2 ], [ 2, %bb2 ] ; <i32> [#uses=1] +; PIC: addis r4, r2, ha16(L_foo_L5-"L1$pb") +; PIC: li r5, lo16(L_foo_L5-"L1$pb") +; PIC: add r4, r4, r5 +; PIC: stw r4 +; STATIC: li r2, lo16(L_foo_L5) +; STATIC: addis r2, r2, ha16(L_foo_L5) +; STATIC: stw r2 + store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4 + ret i32 %res.3 +} |