[llvm] [BPF] Support Jump Table (PR #149715)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 20 11:36:39 PDT 2025
yonghong-song wrote:
I also tried to remove those global variables (with blockaddresses) when gotox is available at pretty late optimizations:
```
diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
index 6275d5b7721c..91768eb1ae3f 100644
--- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp
+++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
@@ -30,6 +30,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include <set>
@@ -308,6 +309,8 @@ struct BPFMIPreEmitPeephole : public MachineFunctionPass {
const TargetRegisterInfo *TRI;
const BPFInstrInfo *TII;
bool SupportGotol;
+ bool SupportGotox;
+ bool doneRemoveUnneededGV = false;
BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {}
@@ -321,6 +324,7 @@ private:
bool insertMissingCallerSavedSpills();
bool removeMayGotoZero();
bool addExitAfterUnreachable();
+ bool removeUnneededGV();
public:
@@ -338,6 +342,8 @@ public:
Changed |= insertMissingCallerSavedSpills();
Changed |= removeMayGotoZero();
Changed |= addExitAfterUnreachable();
+ if (SupportGotox && !doneRemoveUnneededGV)
+ Changed |= removeUnneededGV();
return Changed;
}
};
@@ -348,6 +354,7 @@ void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
SupportGotol = MF->getSubtarget<BPFSubtarget>().hasGotol();
+ SupportGotox = MF->getSubtarget<BPFSubtarget>().hasGotox();
LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
}
@@ -750,6 +757,40 @@ bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
return true;
}
+// Remove global variables which has blockaddress since those global variables
+// have been converted to proper jump tables.
+bool BPFMIPreEmitPeephole::removeUnneededGV() {
+ bool Changed = false;
+ Module *M = MF->getFunction().getParent();
+ std::vector<GlobalVariable *> Targets;
+ for (GlobalVariable &Global : M->globals()) {
+ if (Global.getLinkage() != GlobalValue::PrivateLinkage)
+ continue;
+ if (!Global.isConstant() || !Global.hasInitializer())
+ continue;
+
+ Constant *CV = dyn_cast<Constant>(Global.getInitializer());
+ if (!CV)
+ continue;
+ ConstantArray *CA = dyn_cast<ConstantArray>(CV);
+ if (!CA)
+ continue;
+
+ for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {
+ if (!dyn_cast<BlockAddress>(CA->getOperand(i)))
+ continue;
+ }
+ Targets.push_back(&Global);
+ Changed = true;
+ }
+
+ for (GlobalVariable *GV : Targets)
+ GV->eraseFromParent();
+
+ doneRemoveUnneededGV = true;
+ return Changed;
+}
+
} // end default namespace
INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
```
Unfortunately, tried a few examples, e.g.,
```
struct simple_ctx {
int x;
int y;
int z;
};
int ret_user, ret_user2;
void bar(void);
int foo1(struct simple_ctx *ctx, struct simple_ctx *ctx2)
{
switch (ctx->x) {
case 1: ret_user = 18; break;
case 20: ret_user = 6; break;
case 16: ret_user = 9; break;
case 6: ret_user = 16; break;
case 8: ret_user = 14; break;
case 30: ret_user = 2; break;
default: ret_user = 1; break;
}
bar();
switch (ctx2->x) {
case 0: ret_user2 = 8; break;
case 31: ret_user2 = 5; break;
case 13: ret_user2 = 8; break;
case 1: ret_user2 = 3; break;
case 11: ret_user2 = 4; break;
default: ret_user2 = 29; break;
}
return 0;
}
int foo2(int a, int b) {
__label__ l1, l2, l3, l4;
void *jt1[] = {[0]=&&l1, [1]=&&l2};
void *jt2[] = {[0]=&&l3, [1]=&&l4};
int ret = 0;
goto *jt1[a % 2];
l1: ret += 1;
l2: ret += 3;
goto *jt2[b % 2];
l3: ret += 5;
l4: ret += 7;
return ret;
}
```
It does not work.
As we discussed earlier I think it is okay to leave these unused globals, it does not impact anything except tiny bit space increase.
https://github.com/llvm/llvm-project/pull/149715
More information about the llvm-commits
mailing list