[llvm] [EarlyCSE] merge consecutive bitfield accesses in case of pointers (PR #76053)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 20 06:32:54 PST 2023
https://github.com/adamszilagyi updated https://github.com/llvm/llvm-project/pull/76053
>From b64499c6ef73881378b7e767b31c0fa06e3fe7b4 Mon Sep 17 00:00:00 2001
From: Adam Szilagyi <adam.szilagyi97 at gmail.com>
Date: Wed, 20 Dec 2023 14:12:36 +0100
Subject: [PATCH] [EarlyCSE] merge consecutive bitfield accesses in case of
pointers
---
llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 27 ++++++++++++
llvm/test/Transforms/EarlyCSE/ptrload.ll | 55 ++++++++++++++++++++++++
2 files changed, 82 insertions(+)
create mode 100644 llvm/test/Transforms/EarlyCSE/ptrload.ll
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index f736d429cb6381..5b426089498568 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -1744,6 +1744,33 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
// fallthrough - we can exploit information about this store
}
+ // For loading from pointers we use two load instructions, one for
+ // loading the address and then another one to load the value from the
+ // address.
+ // 0 = load p
+ // x = load 0
+ // ...
+ // store x, 0
+ // In order to be able to remove redundant load/store of this pattern,
+ // before we update the previously stored value load instruction in the
+ // hash table we should update the generation of the pointer load as
+ // well.
+ LoadValue PrevLoad = AvailableLoads.lookup(MemInst.getPointerOperand());
+ if (PrevLoad.DefInst != nullptr) {
+ LoadInst *PtrLoad = dyn_cast<LoadInst>(MemInst.getPointerOperand());
+ if (PtrLoad != nullptr) {
+ ParseMemoryInst PtrMemInst(PtrLoad, TTI);
+ LoadValue PtrLoadVal =
+ AvailableLoads.lookup(PtrMemInst.getPointerOperand());
+ if (PtrLoadVal.DefInst != nullptr)
+ AvailableLoads.insert(PtrMemInst.getPointerOperand(),
+ LoadValue(PtrLoad, CurrentGeneration,
+ PtrMemInst.getMatchingId(),
+ PtrMemInst.isAtomic(),
+ PtrMemInst.isLoad()));
+ }
+ }
+
// Okay, we just invalidated anything we knew about loaded values. Try
// to salvage *something* by remembering that the stored value is a live
// version of the pointer. It is safe to forward from volatile stores
diff --git a/llvm/test/Transforms/EarlyCSE/ptrload.ll b/llvm/test/Transforms/EarlyCSE/ptrload.ll
new file mode 100644
index 00000000000000..7441903a6d87af
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/ptrload.ll
@@ -0,0 +1,55 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=early-cse < %s | FileCheck %s
+
+%struct.bits = type { i8, [3 x i8] }
+
+ at b = dso_local global %struct.bits zeroinitializer, align 4
+
+; Function Attrs: nounwind
+define dso_local arm_aapcscc void @clear_bits() #0 {
+; CHECK-LABEL: @clear_bits(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @b, align 4
+; CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[TMP0]], align 4
+; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -33
+; CHECK-NEXT: [[BF_CLEAR2:%.*]] = and i8 [[BF_CLEAR]], -17
+; CHECK-NEXT: [[BF_CLEAR5:%.*]] = and i8 [[BF_CLEAR2]], -9
+; CHECK-NEXT: [[BF_CLEAR8:%.*]] = and i8 [[BF_CLEAR5]], -5
+; CHECK-NEXT: [[BF_CLEAR11:%.*]] = and i8 [[BF_CLEAR8]], -3
+; CHECK-NEXT: [[BF_CLEAR14:%.*]] = and i8 [[BF_CLEAR11]], -2
+; CHECK-NEXT: store i8 [[BF_CLEAR14]], ptr [[TMP0]], align 4
+; CHECK-NEXT: ret void
+;
+entry:
+ %0 = load ptr, ptr @b, align 4
+ %bf.load = load i8, ptr %0, align 4
+ %bf.clear = and i8 %bf.load, -33
+ %bf.set = or i8 %bf.clear, 0
+ store i8 %bf.set, ptr %0, align 4
+ %1 = load ptr, ptr @b, align 4
+ %bf.load1 = load i8, ptr %1, align 4
+ %bf.clear2 = and i8 %bf.load1, -17
+ %bf.set3 = or i8 %bf.clear2, 0
+ store i8 %bf.set3, ptr %1, align 4
+ %2 = load ptr, ptr @b, align 4
+ %bf.load4 = load i8, ptr %2, align 4
+ %bf.clear5 = and i8 %bf.load4, -9
+ %bf.set6 = or i8 %bf.clear5, 0
+ store i8 %bf.set6, ptr %2, align 4
+ %3 = load ptr, ptr @b, align 4
+ %bf.load7 = load i8, ptr %3, align 4
+ %bf.clear8 = and i8 %bf.load7, -5
+ %bf.set9 = or i8 %bf.clear8, 0
+ store i8 %bf.set9, ptr %3, align 4
+ %4 = load ptr, ptr @b, align 4
+ %bf.load10 = load i8, ptr %4, align 4
+ %bf.clear11 = and i8 %bf.load10, -3
+ %bf.set12 = or i8 %bf.clear11, 0
+ store i8 %bf.set12, ptr %4, align 4
+ %5 = load ptr, ptr @b, align 4
+ %bf.load13 = load i8, ptr %5, align 4
+ %bf.clear14 = and i8 %bf.load13, -2
+ %bf.set15 = or i8 %bf.clear14, 0
+ store i8 %bf.set15, ptr %5, align 4
+ ret void
+}
More information about the llvm-commits
mailing list