Skip to content

Commit eaa8723

Browse files
author
Yonghong Song
committed
[BPF] Lower computed goto and generate proper jump tables
Example 2, Asm code: ... # %bb.0: # %entry r2 = .LJTI0_0 ll r2 = *(u64 *)(r2 + 0) r3 = .LJTI0_1 ll r3 = *(u64 *)(r3 + 0) if w1 == 0 goto LBB0_2 # %bb.1: # %entry r3 = r2 LBB0_2: # %entry *(u64 *)(r10 - 8) = r3 r1 = *(u64 *)(r10 - 8) gotox r1 .Ltmp0: # Block address taken LBB0_3: # %l1 w0 = 3 goto LBB0_5 .Ltmp1: # Block address taken LBB0_4: # %l2 w0 = 2 LBB0_5: # %.split exit ... .section .rodata,"a",@progbits .p2align 3, 0x0 .LJTI0_0: .quad LBB0_3 .LJTI0_1: .quad LBB0_4 Example 3, Asm Code: r3 = (s32)r2 r3 <<= 3 r2 = .LJTI0_0 ll r2 += r3 r1 = (s32)r1 r1 <<= 3 r3 = .LJTI0_1 ll r3 += r1 w0 = 0 r1 = *(u64 *)(r3 + 0) gotox r1 .Ltmp0: # Block address taken LBB0_1: # %l1 # =>This Inner Loop Header: Depth=1 w0 += 1 w0 += 3 r1 = *(u64 *)(r2 + 0) gotox r1 .Ltmp1: # Block address taken LBB0_2: # %l2 # =>This Inner Loop Header: Depth=1 w0 += 3 r1 = *(u64 *)(r2 + 0) gotox r1 .Ltmp2: # Block address taken LBB0_3: # %l3 w0 += 5 goto LBB0_5 .Ltmp3: # Block address taken LBB0_4: # %l4 LBB0_5: # %.split17 w0 += 7 exit ... .section .rodata,"a",@progbits .p2align 3, 0x0 .LJTI0_0: .quad LBB0_3 .quad LBB0_4 .LJTI0_1: .quad LBB0_1 .quad LBB0_2 # -- End function .type .L__const.foo.jt1,@object # @__const.foo.jt1 .p2align 3, 0x0 .L__const.foo.jt1: .quad .Ltmp0 .quad .Ltmp1 .size .L__const.foo.jt1, 16 .type .L__const.foo.jt2,@object # @__const.foo.jt2 .p2align 3, 0x0 .L__const.foo.jt2: .quad .Ltmp2 .quad .Ltmp3 .size .L__const.foo.jt2, 16 Note that for both above examples, the jump table section is '.rodata' and labels have '.L' prefix which means labels won't show up in the symbol table. As mentioned in previous patch, we want to - Move jump tables to '.jumptables' section - Rename '.L*' labels with proper labels which are visible in symbol table. Note that for Example 3, there are extra global functions like .L__const.foo.jt1 and .L__const.foo.jt2 and we are not able to remove them. But they won't show up in symbol table either.
1 parent 64ef0b4 commit eaa8723

File tree

4 files changed

+110
-22
lines changed

4 files changed

+110
-22
lines changed

llvm/lib/Target/BPF/BPFISelLowering.cpp

Lines changed: 102 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -819,23 +819,12 @@ const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const {
819819
return nullptr;
820820
}
821821

822-
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty,
823-
SelectionDAG &DAG, unsigned Flags) {
824-
return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
825-
}
826-
827822
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty,
828823
SelectionDAG &DAG, unsigned Flags) {
829824
return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
830825
N->getOffset(), Flags);
831826
}
832827

833-
static SDValue getTargetNode(BlockAddressSDNode *N, const SDLoc &DL, EVT Ty,
834-
SelectionDAG &DAG, unsigned Flags) {
835-
return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
836-
Flags);
837-
}
838-
839828
static SDValue getTargetNode(JumpTableSDNode *N, const SDLoc &DL, EVT Ty,
840829
SelectionDAG &DAG, unsigned Flags) {
841830
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
@@ -857,7 +846,15 @@ SDValue BPFTargetLowering::LowerGlobalAddress(SDValue Op,
857846
if (N->getOffset() != 0)
858847
report_fatal_error("invalid offset for global address: " +
859848
Twine(N->getOffset()));
860-
return getAddr(N, DAG);
849+
850+
const GlobalValue *GVal = N->getGlobal();
851+
SDLoc DL(Op);
852+
853+
// Wrap it in a TargetGlobalAddress
854+
SDValue Addr = DAG.getTargetGlobalAddress(GVal, DL, MVT::i64);
855+
856+
// Emit pseudo instruction
857+
return SDValue(DAG.getMachineNode(BPF::LDIMM64, DL, MVT::i64, Addr), 0);
861858
}
862859

863860
SDValue BPFTargetLowering::LowerConstantPool(SDValue Op,
@@ -869,8 +866,14 @@ SDValue BPFTargetLowering::LowerConstantPool(SDValue Op,
869866

870867
SDValue BPFTargetLowering::LowerBlockAddress(SDValue Op,
871868
SelectionDAG &DAG) const {
872-
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
873-
return getAddr(N, DAG);
869+
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
870+
SDLoc DL(Op);
871+
872+
// Wrap it in a TargetBlockAddress
873+
SDValue Addr = DAG.getTargetBlockAddress(BA, MVT::i64);
874+
875+
// Emit pseudo instruction
876+
return SDValue(DAG.getMachineNode(BPF::LDIMM64, DL, MVT::i64, Addr), 0);
874877
}
875878

876879
unsigned
@@ -936,6 +939,86 @@ BPFTargetLowering::EmitInstrWithCustomInserterMemcpy(MachineInstr &MI,
936939
return BB;
937940
}
938941

942+
MachineBasicBlock *BPFTargetLowering::EmitInstrWithCustomInserterLDimm64(
943+
MachineInstr &MI, MachineBasicBlock *BB) const {
944+
MachineFunction *MF = BB->getParent();
945+
const BPFInstrInfo *TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
946+
const TargetRegisterClass *RC = getRegClassFor(MVT::i64);
947+
MachineRegisterInfo &RegInfo = MF->getRegInfo();
948+
DebugLoc DL = MI.getDebugLoc();
949+
950+
// Build address taken map for Global Varaibles and BlockAddresses
951+
DenseMap<const BasicBlock *, MachineBasicBlock *> AddressTakenBBs;
952+
for (MachineBasicBlock &MBB : *MF) {
953+
if (const BasicBlock *BB = MBB.getBasicBlock())
954+
if (BB->hasAddressTaken())
955+
AddressTakenBBs[BB] = &MBB;
956+
}
957+
958+
MachineOperand &MO = MI.getOperand(1);
959+
assert(MO.isBlockAddress() || MO.isGlobal());
960+
961+
MCRegister ResultReg = MI.getOperand(0).getReg();
962+
Register TmpReg = RegInfo.createVirtualRegister(RC);
963+
964+
std::vector<MachineBasicBlock *> Targets;
965+
unsigned JTI;
966+
967+
if (MO.isBlockAddress()) {
968+
auto *BA = MO.getBlockAddress();
969+
MachineBasicBlock *TgtMBB = AddressTakenBBs[BA->getBasicBlock()];
970+
assert(TgtMBB);
971+
972+
Targets.push_back(TgtMBB);
973+
JTI = MF->getOrCreateJumpTableInfo(getJumpTableEncoding())
974+
->createJumpTableIndex(Targets);
975+
976+
BuildMI(*BB, MI, DL, TII->get(BPF::LD_imm64), TmpReg)
977+
.addJumpTableIndex(JTI);
978+
BuildMI(*BB, MI, DL, TII->get(BPF::LDD), ResultReg)
979+
.addReg(TmpReg)
980+
.addImm(0);
981+
MI.eraseFromParent();
982+
return BB;
983+
}
984+
985+
// Helper: emit LD_imm64 with operand GlobalAddress or JumpTable
986+
auto emitLDImm64 = [&](const GlobalValue *GV = nullptr, unsigned JTI = -1) {
987+
auto MIB = BuildMI(*BB, MI, DL, TII->get(BPF::LD_imm64), ResultReg);
988+
if (GV)
989+
MIB.addGlobalAddress(GV);
990+
else
991+
MIB.addJumpTableIndex(JTI);
992+
MI.eraseFromParent();
993+
return BB;
994+
};
995+
996+
// Must be a global at this point
997+
const GlobalValue *GVal = MO.getGlobal();
998+
const auto *GV = dyn_cast<GlobalVariable>(GVal);
999+
1000+
if (!GV || GV->getLinkage() != GlobalValue::PrivateLinkage ||
1001+
!GV->isConstant() || !GV->hasInitializer())
1002+
return emitLDImm64(GVal);
1003+
1004+
const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1005+
if (!CA)
1006+
return emitLDImm64(GVal);
1007+
1008+
for (const Use &Op : CA->operands()) {
1009+
if (!isa<BlockAddress>(Op))
1010+
return emitLDImm64(GVal);
1011+
auto *BA = cast<BlockAddress>(Op);
1012+
MachineBasicBlock *TgtMBB = AddressTakenBBs[BA->getBasicBlock()];
1013+
assert(TgtMBB);
1014+
Targets.push_back(TgtMBB);
1015+
}
1016+
1017+
JTI = MF->getOrCreateJumpTableInfo(getJumpTableEncoding())
1018+
->createJumpTableIndex(Targets);
1019+
return emitLDImm64(nullptr, JTI);
1020+
}
1021+
9391022
MachineBasicBlock *
9401023
BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
9411024
MachineBasicBlock *BB) const {
@@ -948,20 +1031,24 @@ BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
9481031
Opc == BPF::Select_32_64);
9491032

9501033
bool isMemcpyOp = Opc == BPF::MEMCPY;
1034+
bool isLDimm64Op = Opc == BPF::LDIMM64;
9511035

9521036
#ifndef NDEBUG
9531037
bool isSelectRIOp = (Opc == BPF::Select_Ri ||
9541038
Opc == BPF::Select_Ri_64_32 ||
9551039
Opc == BPF::Select_Ri_32 ||
9561040
Opc == BPF::Select_Ri_32_64);
9571041

958-
if (!(isSelectRROp || isSelectRIOp || isMemcpyOp))
1042+
if (!(isSelectRROp || isSelectRIOp || isMemcpyOp || isLDimm64Op))
9591043
report_fatal_error("unhandled instruction type: " + Twine(Opc));
9601044
#endif
9611045

9621046
if (isMemcpyOp)
9631047
return EmitInstrWithCustomInserterMemcpy(MI, BB);
9641048

1049+
if (isLDimm64Op)
1050+
return EmitInstrWithCustomInserterLDimm64(MI, BB);
1051+
9651052
bool is32BitCmp = (Opc == BPF::Select_32 ||
9661053
Opc == BPF::Select_32_64 ||
9671054
Opc == BPF::Select_Ri_32 ||

llvm/lib/Target/BPF/BPFISelLowering.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ class BPFTargetLowering : public TargetLowering {
167167
MachineBasicBlock * EmitInstrWithCustomInserterMemcpy(MachineInstr &MI,
168168
MachineBasicBlock *BB)
169169
const;
170-
170+
MachineBasicBlock *
171+
EmitInstrWithCustomInserterLDimm64(MachineInstr &MI,
172+
MachineBasicBlock *BB) const;
171173
};
172174
}
173175

llvm/lib/Target/BPF/BPFInstrInfo.td

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,7 @@ let usesCustomInserter = 1, isCodeGenOnly = 1 in {
865865
}
866866

867867
// load 64-bit global addr into register
868-
def : Pat<(BPFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>;
869868
def : Pat<(BPFWrapper tconstpool:$in), (LD_imm64 tconstpool:$in)>;
870-
def : Pat<(BPFWrapper tblockaddress:$in), (LD_imm64 tblockaddress:$in)>;
871869
def : Pat<(BPFWrapper tjumptable:$in), (LD_imm64 tjumptable:$in)>;
872870

873871
// 0xffffFFFF doesn't fit into simm32, optimize common case
@@ -1388,3 +1386,8 @@ let usesCustomInserter = 1, isCodeGenOnly = 1 in {
13881386
"#memcpy dst: $dst, src: $src, len: $len, align: $align",
13891387
[(BPFmemcpy GPR:$dst, GPR:$src, imm:$len, imm:$align)]>;
13901388
}
1389+
1390+
// For GlobalValue and BlockAddress.
1391+
let usesCustomInserter = 1, isCodeGenOnly = 1 in {
1392+
def LDIMM64 : Pseudo<(outs GPR:$dst), (ins i64imm:$addr), "", []>;
1393+
}

llvm/lib/Target/BPF/BPFMCInstLower.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ void BPFMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
8080
case MachineOperand::MO_JumpTableIndex:
8181
MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
8282
break;
83-
case MachineOperand::MO_BlockAddress:
84-
MCOp = LowerSymbolOperand(
85-
MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
86-
break;
8783
}
8884

8985
OutMI.addOperand(MCOp);

0 commit comments

Comments
 (0)