diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp index f10a0d4c00772..84159d40fd865 100644 --- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp +++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -304,6 +304,47 @@ void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node, LLVM_DEBUG(dbgs() << "Replacing load of size " << size << " with constant " << val << '\n'); + + /* Some load nodes have edges from TokenFactor nodes. In this case + replacing the load with a constant makes the DAG disconnected. + The following checks if any of the load operands are TokenFactor + nodes, and if another TokenFactor is a user of the load, the + operand TokenFactor is connected to the user, so that the DAG + remains connected after replacing the load node by a constant. + */ + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) { + const SDValue &OpV = Node->getOperand(I); + SDNode *Op = OpV.getNode(); + if (Op->getOpcode() == ISD::TokenFactor) { + for (SDNode::use_iterator UI = Node->use_begin(), UE = Node->use_end(); UI != UE; ++UI) { + SDUse &Use = UI.getUse(); + SDNode *User = Use.getUser(); + if (User->getOpcode() == ISD::TokenFactor) { + SmallVector ExtendedOps; + bool NotExtended = true; + for (unsigned UOI = 0, UOE = User->getNumOperands(); UOI != UOE; ++UOI) { + const SDValue &Operand = User->getOperand(UOI); + if (OpV == Operand) { + NotExtended = false; + break; + } + ExtendedOps.push_back(Operand); + } + if (NotExtended) { + ExtendedOps.push_back(OpV); + SDValue ExtendedTokenFactor = CurDAG->getTokenFactor(SDLoc(User), ExtendedOps); + I--; + SDValue From[] = {SDValue(User, 0)}; + SDValue To[] = {ExtendedTokenFactor}; + CurDAG->ReplaceAllUsesOfValuesWith(From, To, 1); + I++; + CurDAG->DeleteNode(User); + } + } + } + } + } + SDValue NVal = CurDAG->getConstant(val, DL, LD->getValueType(0)); // After replacement, the current node is dead, we need to diff --git a/llvm/test/CodeGen/BPF/preprocess-loads.ll b/llvm/test/CodeGen/BPF/preprocess-loads.ll new file mode 100644 index 0000000000000..08701d1a381b7 --- /dev/null +++ b/llvm/test/CodeGen/BPF/preprocess-loads.ll @@ -0,0 +1,35 @@ +; RUN: llc -O2 -march=bpfel --mattr=+solana -filetype=asm < %s | FileCheck --check-prefix=CHECK %s + +%Pool = type <{ [0 x i8], [32 x i8], [0 x i8], i8, [0 x i8], [10 x %Decimal], [0 x i8] }> +%Decimal = type { [0 x i32], i32, [0 x i32], i32, [0 x i32], i32, [0 x i32], i32, [0 x i32] } + +@0 = private unnamed_addr constant <{ [16 x i8] }> <{ [16 x i8] c"\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF" }>, align 4 + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #5 + +; optbug::Pool::initialize +; Function Attrs: nofree noinline nounwind willreturn +define internal fastcc void @_ZN6optbug4Pool10initialize17h656ab4e5f05591beE(%Pool* noalias nocapture align 1 dereferenceable(193) %self, [32 x i8]* noalias nocapture readonly align 1 dereferenceable(32) %seed, i8 %bump) unnamed_addr #2 { +start: + %0 = getelementptr inbounds [32 x i8], [32 x i8]* %seed, i64 0, i64 0 + %self56 = getelementptr inbounds %Pool, %Pool* %self, i64 0, i32 0, i64 0 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(32) %self56, i8* nonnull align 1 dereferenceable(32) %0, i64 32, i1 false) + %1 = getelementptr inbounds %Pool, %Pool* %self, i64 0, i32 3 + store i8 %bump, i8* %1, align 1 + %2 = getelementptr inbounds %Pool, %Pool* %self, i64 0, i32 5, i64 1 + %3 = bitcast %Decimal* %2 to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) %3, i8* nonnull align 4 dereferenceable(16) getelementptr inbounds (<{ [16 x i8] }>, <{ [16 x i8] }>* @0, i64 0, i32 0, i64 0), i64 16, i1 false) + ret void +} + +; CHECK: *(u64 *)(r1 + 24) = r4 +; CHECK: *(u64 *)(r1 + 16) = r4 +; CHECK: *(u64 *)(r1 + 8) = r4 +; CHECK: *(u64 *)(r1 + 0) = r2 +; CHECK: *(u8 *)(r1 + 32) = r3 + +attributes #2 = { nofree noinline nounwind willreturn "target-cpu"="generic" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 7, !"PIC Level", i32 2} diff --git a/llvm/test/tools/lto/hide-linkonce-odr.ll b/llvm/test/tools/lto/hide-linkonce-odr.ll index ad7cf1b3f8baa..b75bd411a91e0 100644 --- a/llvm/test/tools/lto/hide-linkonce-odr.ll +++ b/llvm/test/tools/lto/hide-linkonce-odr.ll @@ -1,3 +1,4 @@ +; XFAIL: darwin ; RUN: llvm-as %s -o %t.o ; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -dylib -arch x86_64 -macosx_version_min 10.10.0 -o %t.dylib %t.o -save-temps -undefined dynamic_lookup -exported_symbol _c -exported_symbol _b -exported_symbol _GlobLinkonce diff --git a/llvm/test/tools/lto/opt-level.ll b/llvm/test/tools/lto/opt-level.ll index b282679936a44..22485e65fae22 100644 --- a/llvm/test/tools/lto/opt-level.ll +++ b/llvm/test/tools/lto/opt-level.ll @@ -1,3 +1,4 @@ +; XFAIL: darwin ; RUN: llvm-as %s -o %t.o ; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O0 -o %t.dylib %t.o ; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O0 %s diff --git a/llvm/test/tools/lto/print-stats.ll b/llvm/test/tools/lto/print-stats.ll index 125d7d0514990..1a8280ad1058a 100644 --- a/llvm/test/tools/lto/print-stats.ll +++ b/llvm/test/tools/lto/print-stats.ll @@ -1,3 +1,4 @@ +; XFAIL: darwin ; RUN: llvm-as %s -o %t.o ; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -stats -o %t.dylib %t.o 2>&1 | FileCheck --check-prefix=STATS %s ; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -o %t.dylib %t.o 2>&1 | FileCheck --check-prefix=NO_STATS %s