[llvm-branch-commits] [llvm] [GVN] Don't coerce forwarded byte values through integers (PR #226583)
Pedro Lobo via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 6 05:03:58 PDT 2026
https://github.com/pedroclobo updated https://github.com/llvm/llvm-project/pull/226583
>From a63069c462a849ee45b664770d844e2477466d5d Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Mon, 5 Oct 2026 15:19:49 +0100
Subject: [PATCH 1/2] [GVN] Pre-commit tests for byte conversions
---
llvm/test/Transforms/GVN/byte-conversion.ll | 278 ++++++++++++++++++++
1 file changed, 278 insertions(+)
create mode 100644 llvm/test/Transforms/GVN/byte-conversion.ll
diff --git a/llvm/test/Transforms/GVN/byte-conversion.ll b/llvm/test/Transforms/GVN/byte-conversion.ll
new file mode 100644
index 000000000000000..301f00606a38224
--- /dev/null
+++ b/llvm/test/Transforms/GVN/byte-conversion.ll
@@ -0,0 +1,278 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -data-layout="e-p:64:64:64-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8:16:32:64" -passes=gvn -S | FileCheck %s --check-prefixes=CHECK,LE
+; RUN: opt < %s -data-layout="E-p:64:64:64-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8:16:32:64" -passes=gvn -S | FileCheck %s --check-prefixes=CHECK,BE
+
+declare void @use(b32) memory(none)
+
+define b8 @b32_store_to_b8_load(ptr %p, b32 %x) {
+; LE-LABEL: define b8 @b32_store_to_b8_load(
+; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
+; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; LE-NEXT: ret b8 [[TMP4]]
+;
+; BE-LABEL: define b8 @b32_store_to_b8_load(
+; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
+; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; BE-NEXT: ret b8 [[TMP4]]
+;
+ store b32 %x, ptr %p, align 4
+ %q = getelementptr i8, ptr %p, i64 1
+ %v = load b8, ptr %q, align 1
+ ret b8 %v
+}
+
+define i16 @b32_store_to_i16_load(ptr %p, b32 %x) {
+; LE-LABEL: define i16 @b32_store_to_i16_load(
+; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; LE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; LE-NEXT: ret i16 [[TMP2]]
+;
+; BE-LABEL: define i16 @b32_store_to_i16_load(
+; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
+; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
+; BE-NEXT: ret i16 [[TMP3]]
+;
+ store b32 %x, ptr %p, align 4
+ %v = load i16, ptr %p, align 2
+ ret i16 %v
+}
+
+define b3 @b32_store_to_b3_load(ptr %p, b32 %x) {
+; LE-LABEL: define b3 @b32_store_to_b3_load(
+; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; LE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8
+; LE-NEXT: [[TMP3:%.*]] = trunc i8 [[TMP2]] to i3
+; LE-NEXT: [[TMP4:%.*]] = bitcast i3 [[TMP3]] to b3
+; LE-NEXT: ret b3 [[TMP4]]
+;
+; BE-LABEL: define b3 @b32_store_to_b3_load(
+; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
+; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; BE-NEXT: [[TMP4:%.*]] = trunc i8 [[TMP3]] to i3
+; BE-NEXT: [[TMP5:%.*]] = bitcast i3 [[TMP4]] to b3
+; BE-NEXT: ret b3 [[TMP5]]
+;
+ store b32 %x, ptr %p, align 4
+ %v = load b3, ptr %p, align 1
+ ret b3 %v
+}
+
+define ptr @b64_store_to_ptr_load(ptr %p, b64 %x) {
+; CHECK-LABEL: define ptr @b64_store_to_ptr_load(
+; CHECK-SAME: ptr [[P:%.*]], b64 [[X:%.*]]) {
+; CHECK-NEXT: store b64 [[X]], ptr [[P]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast b64 [[X]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
+; CHECK-NEXT: ret ptr [[TMP2]]
+;
+ store b64 %x, ptr %p, align 8
+ %v = load ptr, ptr %p, align 8
+ ret ptr %v
+}
+
+define ptr @b128_store_to_ptr_load(ptr %p, b128 %x) {
+; LE-LABEL: define ptr @b128_store_to_ptr_load(
+; LE-SAME: ptr [[P:%.*]], b128 [[X:%.*]]) {
+; LE-NEXT: store b128 [[X]], ptr [[P]], align 8
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 8
+; LE-NEXT: [[TMP1:%.*]] = bitcast b128 [[X]] to i128
+; LE-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64
+; LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64
+; LE-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
+; LE-NEXT: ret ptr [[TMP4]]
+;
+; BE-LABEL: define ptr @b128_store_to_ptr_load(
+; BE-SAME: ptr [[P:%.*]], b128 [[X:%.*]]) {
+; BE-NEXT: store b128 [[X]], ptr [[P]], align 8
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 8
+; BE-NEXT: [[TMP1:%.*]] = bitcast b128 [[X]] to i128
+; BE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64
+; BE-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
+; BE-NEXT: ret ptr [[TMP3]]
+;
+ store b128 %x, ptr %p, align 8
+ %q = getelementptr i8, ptr %p, i64 8
+ %v = load ptr, ptr %q, align 8
+ ret ptr %v
+}
+
+define <2 x b8> @b32_store_to_v2b8_load(ptr %p, b32 %x) {
+; LE-LABEL: define <2 x b8> @b32_store_to_v2b8_load(
+; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
+; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
+; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
+; LE-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP3]] to <2 x b8>
+; LE-NEXT: ret <2 x b8> [[TMP4]]
+;
+; BE-LABEL: define <2 x b8> @b32_store_to_v2b8_load(
+; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
+; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
+; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
+; BE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+; BE-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to <2 x b8>
+; BE-NEXT: ret <2 x b8> [[TMP3]]
+;
+ store b32 %x, ptr %p, align 4
+ %q = getelementptr i8, ptr %p, i64 2
+ %v = load <2 x b8>, ptr %q, align 1
+ ret <2 x b8> %v
+}
+
+define b8 @b24_store_to_b8_load(ptr %p, b24 %x) {
+; LE-LABEL: define b8 @b24_store_to_b8_load(
+; LE-SAME: ptr [[P:%.*]], b24 [[X:%.*]]) {
+; LE-NEXT: store b24 [[X]], ptr [[P]], align 4
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
+; LE-NEXT: [[TMP1:%.*]] = bitcast b24 [[X]] to i24
+; LE-NEXT: [[TMP2:%.*]] = lshr i24 [[TMP1]], 16
+; LE-NEXT: [[TMP3:%.*]] = trunc i24 [[TMP2]] to i8
+; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; LE-NEXT: ret b8 [[TMP4]]
+;
+; BE-LABEL: define b8 @b24_store_to_b8_load(
+; BE-SAME: ptr [[P:%.*]], b24 [[X:%.*]]) {
+; BE-NEXT: store b24 [[X]], ptr [[P]], align 4
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
+; BE-NEXT: [[TMP1:%.*]] = bitcast b24 [[X]] to i24
+; BE-NEXT: [[TMP2:%.*]] = trunc i24 [[TMP1]] to i8
+; BE-NEXT: [[TMP3:%.*]] = bitcast i8 [[TMP2]] to b8
+; BE-NEXT: ret b8 [[TMP3]]
+;
+ store b24 %x, ptr %p, align 4
+ %q = getelementptr i8, ptr %p, i64 2
+ %v = load b8, ptr %q, align 1
+ ret b8 %v
+}
+
+define b8 @b32_load_to_b8_load(ptr %p) {
+; LE-LABEL: define b8 @b32_load_to_b8_load(
+; LE-SAME: ptr [[P:%.*]]) {
+; LE-NEXT: [[A:%.*]] = load b32, ptr [[P]], align 4
+; LE-NEXT: call void @use(b32 [[A]])
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[A]] to i32
+; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
+; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; LE-NEXT: ret b8 [[TMP4]]
+;
+; BE-LABEL: define b8 @b32_load_to_b8_load(
+; BE-SAME: ptr [[P:%.*]]) {
+; BE-NEXT: [[A:%.*]] = load b32, ptr [[P]], align 4
+; BE-NEXT: call void @use(b32 [[A]])
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[A]] to i32
+; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
+; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; BE-NEXT: ret b8 [[TMP4]]
+;
+ %a = load b32, ptr %p, align 4
+ call void @use(b32 %a)
+ %q = getelementptr i8, ptr %p, i64 1
+ %v = load b8, ptr %q, align 1
+ ret b8 %v
+}
+
+define b8 @v4b8_store_to_b8_load(ptr %p, <4 x b8> %x) {
+; LE-LABEL: define b8 @v4b8_store_to_b8_load(
+; LE-SAME: ptr [[P:%.*]], <4 x b8> [[X:%.*]]) {
+; LE-NEXT: store <4 x b8> [[X]], ptr [[P]], align 4
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; LE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to i32
+; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
+; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; LE-NEXT: ret b8 [[TMP4]]
+;
+; BE-LABEL: define b8 @v4b8_store_to_b8_load(
+; BE-SAME: ptr [[P:%.*]], <4 x b8> [[X:%.*]]) {
+; BE-NEXT: store <4 x b8> [[X]], ptr [[P]], align 4
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
+; BE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to i32
+; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
+; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
+; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
+; BE-NEXT: ret b8 [[TMP4]]
+;
+ store <4 x b8> %x, ptr %p, align 4
+ %q = getelementptr i8, ptr %p, i64 1
+ %v = load b8, ptr %q, align 1
+ ret b8 %v
+}
+
+define b32 @ptr_store_to_b32_load(ptr %p, ptr %x) {
+; LE-LABEL: define b32 @ptr_store_to_b32_load(
+; LE-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
+; LE-NEXT: store ptr [[X]], ptr [[P]], align 8
+; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 4
+; LE-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
+; LE-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 32
+; LE-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
+; LE-NEXT: [[TMP4:%.*]] = bitcast i32 [[TMP3]] to b32
+; LE-NEXT: ret b32 [[TMP4]]
+;
+; BE-LABEL: define b32 @ptr_store_to_b32_load(
+; BE-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
+; BE-NEXT: store ptr [[X]], ptr [[P]], align 8
+; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 4
+; BE-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
+; BE-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; BE-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to b32
+; BE-NEXT: ret b32 [[TMP3]]
+;
+ store ptr %x, ptr %p, align 8
+ %q = getelementptr i8, ptr %p, i64 4
+ %v = load b32, ptr %q, align 4
+ ret b32 %v
+}
+
+define b64 @ptr_store_to_b64_load(ptr %p, ptr %x) {
+; CHECK-LABEL: define b64 @ptr_store_to_b64_load(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT: store ptr [[X]], ptr [[P]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to b64
+; CHECK-NEXT: ret b64 [[TMP2]]
+;
+ store ptr %x, ptr %p, align 8
+ %v = load b64, ptr %p, align 8
+ ret b64 %v
+}
+
+define b32 @b64_zero_store_to_b32_load(ptr %p) {
+; CHECK-LABEL: define b32 @b64_zero_store_to_b32_load(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: store b64 0, ptr [[P]], align 8
+; CHECK-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 4
+; CHECK-NEXT: ret b32 0
+;
+ store b64 0, ptr %p
+ %q = getelementptr i8, ptr %p, i64 4
+ %v = load b32, ptr %q
+ ret b32 %v
+}
>From 799e5e809f3c1bf87166f52449292c239f0c814b Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Mon, 5 Oct 2026 15:19:50 +0100
Subject: [PATCH 2/2] [GVN] Don't coerce forwarded byte values through integers
---
llvm/lib/Transforms/Utils/VNCoercion.cpp | 31 ++++-
llvm/test/Transforms/GVN/byte-conversion.ll | 136 +++++++-------------
2 files changed, 71 insertions(+), 96 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/VNCoercion.cpp b/llvm/lib/Transforms/Utils/VNCoercion.cpp
index 0dabd065b6723ee..0df5bd12ceabe26 100644
--- a/llvm/lib/Transforms/Utils/VNCoercion.cpp
+++ b/llvm/lib/Transforms/Utils/VNCoercion.cpp
@@ -352,6 +352,31 @@ static Value *getStoreValueForLoadHelper(Value *SrcVal, unsigned Offset,
uint64_t StoreSize =
(DL.getTypeSizeInBits(SrcVal->getType()).getFixedValue() + 7) / 8;
uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy).getFixedValue() + 7) / 8;
+
+ // Shift the bits to the least significant depending on endianness.
+ unsigned ShiftAmt;
+ if (DL.isLittleEndian())
+ ShiftAmt = Offset * 8;
+ else
+ ShiftAmt = (StoreSize - LoadSize - Offset) * 8;
+
+ Type *SrcTy = SrcVal->getType();
+ // Integers drop provenance, and one poison bit poisons the whole value.
+ if (SrcTy->isByteOrByteVectorTy() ||
+ (SrcTy->isPtrOrPtrVectorTy() && LoadTy->isByteOrByteVectorTy())) {
+ unsigned SrcBits = DL.getTypeSizeInBits(SrcTy).getFixedValue();
+ unsigned LoadBits = DL.getTypeSizeInBits(LoadTy).getFixedValue();
+ if (LoadBits == SrcBits)
+ return Builder.CreateBitCast(SrcVal, LoadTy);
+ // bitextract needs a scalar byte source and can't return a vector.
+ SrcVal = Builder.CreateBitCast(SrcVal, Type::getByteNTy(Ctx, SrcBits));
+ Type *ExtractTy =
+ LoadTy->isVectorTy() ? Type::getByteNTy(Ctx, LoadBits) : LoadTy;
+ SrcVal =
+ Builder.CreateBitExtract(ExtractTy, SrcVal, Builder.getInt32(ShiftAmt));
+ return Builder.CreateBitCast(SrcVal, LoadTy);
+ }
+
// Compute which bits of the stored value are being used by the load. Convert
// to an integer type to start with.
if (SrcVal->getType()->isPtrOrPtrVectorTy())
@@ -361,12 +386,6 @@ static Value *getStoreValueForLoadHelper(Value *SrcVal, unsigned Offset,
SrcVal =
Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize * 8));
- // Shift the bits to the least significant depending on endianness.
- unsigned ShiftAmt;
- if (DL.isLittleEndian())
- ShiftAmt = Offset * 8;
- else
- ShiftAmt = (StoreSize - LoadSize - Offset) * 8;
if (ShiftAmt)
SrcVal = Builder.CreateLShr(SrcVal,
ConstantInt::get(SrcVal->getType(), ShiftAmt));
diff --git a/llvm/test/Transforms/GVN/byte-conversion.ll b/llvm/test/Transforms/GVN/byte-conversion.ll
index 301f00606a38224..7d9650e1a6f9c3d 100644
--- a/llvm/test/Transforms/GVN/byte-conversion.ll
+++ b/llvm/test/Transforms/GVN/byte-conversion.ll
@@ -9,21 +9,15 @@ define b8 @b32_store_to_b8_load(ptr %p, b32 %x) {
; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
-; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; LE-NEXT: ret b8 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract b8, b32 [[X]], i32 8
+; LE-NEXT: ret b8 [[TMP1]]
;
; BE-LABEL: define b8 @b32_store_to_b8_load(
; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
-; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; BE-NEXT: ret b8 [[TMP4]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract b8, b32 [[X]], i32 16
+; BE-NEXT: ret b8 [[TMP1]]
;
store b32 %x, ptr %p, align 4
%q = getelementptr i8, ptr %p, i64 1
@@ -35,17 +29,14 @@ define i16 @b32_store_to_i16_load(ptr %p, b32 %x) {
; LE-LABEL: define i16 @b32_store_to_i16_load(
; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
-; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; LE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
-; LE-NEXT: ret i16 [[TMP2]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract i16, b32 [[X]], i32 0
+; LE-NEXT: ret i16 [[TMP1]]
;
; BE-LABEL: define i16 @b32_store_to_i16_load(
; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
-; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
-; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
-; BE-NEXT: ret i16 [[TMP3]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract i16, b32 [[X]], i32 16
+; BE-NEXT: ret i16 [[TMP1]]
;
store b32 %x, ptr %p, align 4
%v = load i16, ptr %p, align 2
@@ -56,21 +47,14 @@ define b3 @b32_store_to_b3_load(ptr %p, b32 %x) {
; LE-LABEL: define b3 @b32_store_to_b3_load(
; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
-; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; LE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8
-; LE-NEXT: [[TMP3:%.*]] = trunc i8 [[TMP2]] to i3
-; LE-NEXT: [[TMP4:%.*]] = bitcast i3 [[TMP3]] to b3
-; LE-NEXT: ret b3 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract b3, b32 [[X]], i32 0
+; LE-NEXT: ret b3 [[TMP1]]
;
; BE-LABEL: define b3 @b32_store_to_b3_load(
; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
-; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
-; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; BE-NEXT: [[TMP4:%.*]] = trunc i8 [[TMP3]] to i3
-; BE-NEXT: [[TMP5:%.*]] = bitcast i3 [[TMP4]] to b3
-; BE-NEXT: ret b3 [[TMP5]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract b3, b32 [[X]], i32 24
+; BE-NEXT: ret b3 [[TMP1]]
;
store b32 %x, ptr %p, align 4
%v = load b3, ptr %p, align 1
@@ -81,9 +65,8 @@ define ptr @b64_store_to_ptr_load(ptr %p, b64 %x) {
; CHECK-LABEL: define ptr @b64_store_to_ptr_load(
; CHECK-SAME: ptr [[P:%.*]], b64 [[X:%.*]]) {
; CHECK-NEXT: store b64 [[X]], ptr [[P]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = bitcast b64 [[X]] to i64
-; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
-; CHECK-NEXT: ret ptr [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast b64 [[X]] to ptr
+; CHECK-NEXT: ret ptr [[TMP1]]
;
store b64 %x, ptr %p, align 8
%v = load ptr, ptr %p, align 8
@@ -95,20 +78,15 @@ define ptr @b128_store_to_ptr_load(ptr %p, b128 %x) {
; LE-SAME: ptr [[P:%.*]], b128 [[X:%.*]]) {
; LE-NEXT: store b128 [[X]], ptr [[P]], align 8
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 8
-; LE-NEXT: [[TMP1:%.*]] = bitcast b128 [[X]] to i128
-; LE-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64
-; LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64
-; LE-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
-; LE-NEXT: ret ptr [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract ptr, b128 [[X]], i32 64
+; LE-NEXT: ret ptr [[TMP1]]
;
; BE-LABEL: define ptr @b128_store_to_ptr_load(
; BE-SAME: ptr [[P:%.*]], b128 [[X:%.*]]) {
; BE-NEXT: store b128 [[X]], ptr [[P]], align 8
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 8
-; BE-NEXT: [[TMP1:%.*]] = bitcast b128 [[X]] to i128
-; BE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64
-; BE-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
-; BE-NEXT: ret ptr [[TMP3]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract ptr, b128 [[X]], i32 0
+; BE-NEXT: ret ptr [[TMP1]]
;
store b128 %x, ptr %p, align 8
%q = getelementptr i8, ptr %p, i64 8
@@ -121,20 +99,17 @@ define <2 x b8> @b32_store_to_v2b8_load(ptr %p, b32 %x) {
; LE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; LE-NEXT: store b32 [[X]], ptr [[P]], align 4
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
-; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
-; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
-; LE-NEXT: [[TMP4:%.*]] = bitcast i16 [[TMP3]] to <2 x b8>
-; LE-NEXT: ret <2 x b8> [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract b16, b32 [[X]], i32 16
+; LE-NEXT: [[TMP2:%.*]] = bitcast b16 [[TMP1]] to <2 x b8>
+; LE-NEXT: ret <2 x b8> [[TMP2]]
;
; BE-LABEL: define <2 x b8> @b32_store_to_v2b8_load(
; BE-SAME: ptr [[P:%.*]], b32 [[X:%.*]]) {
; BE-NEXT: store b32 [[X]], ptr [[P]], align 4
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
-; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[X]] to i32
-; BE-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
-; BE-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to <2 x b8>
-; BE-NEXT: ret <2 x b8> [[TMP3]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract b16, b32 [[X]], i32 0
+; BE-NEXT: [[TMP2:%.*]] = bitcast b16 [[TMP1]] to <2 x b8>
+; BE-NEXT: ret <2 x b8> [[TMP2]]
;
store b32 %x, ptr %p, align 4
%q = getelementptr i8, ptr %p, i64 2
@@ -147,20 +122,15 @@ define b8 @b24_store_to_b8_load(ptr %p, b24 %x) {
; LE-SAME: ptr [[P:%.*]], b24 [[X:%.*]]) {
; LE-NEXT: store b24 [[X]], ptr [[P]], align 4
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
-; LE-NEXT: [[TMP1:%.*]] = bitcast b24 [[X]] to i24
-; LE-NEXT: [[TMP2:%.*]] = lshr i24 [[TMP1]], 16
-; LE-NEXT: [[TMP3:%.*]] = trunc i24 [[TMP2]] to i8
-; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; LE-NEXT: ret b8 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract b8, b24 [[X]], i32 16
+; LE-NEXT: ret b8 [[TMP1]]
;
; BE-LABEL: define b8 @b24_store_to_b8_load(
; BE-SAME: ptr [[P:%.*]], b24 [[X:%.*]]) {
; BE-NEXT: store b24 [[X]], ptr [[P]], align 4
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 2
-; BE-NEXT: [[TMP1:%.*]] = bitcast b24 [[X]] to i24
-; BE-NEXT: [[TMP2:%.*]] = trunc i24 [[TMP1]] to i8
-; BE-NEXT: [[TMP3:%.*]] = bitcast i8 [[TMP2]] to b8
-; BE-NEXT: ret b8 [[TMP3]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract b8, b24 [[X]], i32 0
+; BE-NEXT: ret b8 [[TMP1]]
;
store b24 %x, ptr %p, align 4
%q = getelementptr i8, ptr %p, i64 2
@@ -174,22 +144,16 @@ define b8 @b32_load_to_b8_load(ptr %p) {
; LE-NEXT: [[A:%.*]] = load b32, ptr [[P]], align 4
; LE-NEXT: call void @use(b32 [[A]])
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; LE-NEXT: [[TMP1:%.*]] = bitcast b32 [[A]] to i32
-; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
-; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; LE-NEXT: ret b8 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitextract b8, b32 [[A]], i32 8
+; LE-NEXT: ret b8 [[TMP1]]
;
; BE-LABEL: define b8 @b32_load_to_b8_load(
; BE-SAME: ptr [[P:%.*]]) {
; BE-NEXT: [[A:%.*]] = load b32, ptr [[P]], align 4
; BE-NEXT: call void @use(b32 [[A]])
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; BE-NEXT: [[TMP1:%.*]] = bitcast b32 [[A]] to i32
-; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
-; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; BE-NEXT: ret b8 [[TMP4]]
+; BE-NEXT: [[TMP1:%.*]] = bitextract b8, b32 [[A]], i32 16
+; BE-NEXT: ret b8 [[TMP1]]
;
%a = load b32, ptr %p, align 4
call void @use(b32 %a)
@@ -203,21 +167,17 @@ define b8 @v4b8_store_to_b8_load(ptr %p, <4 x b8> %x) {
; LE-SAME: ptr [[P:%.*]], <4 x b8> [[X:%.*]]) {
; LE-NEXT: store <4 x b8> [[X]], ptr [[P]], align 4
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; LE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to i32
-; LE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 8
-; LE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; LE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; LE-NEXT: ret b8 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to b32
+; LE-NEXT: [[TMP2:%.*]] = bitextract b8, b32 [[TMP1]], i32 8
+; LE-NEXT: ret b8 [[TMP2]]
;
; BE-LABEL: define b8 @v4b8_store_to_b8_load(
; BE-SAME: ptr [[P:%.*]], <4 x b8> [[X:%.*]]) {
; BE-NEXT: store <4 x b8> [[X]], ptr [[P]], align 4
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 1
-; BE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to i32
-; BE-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
-; BE-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
-; BE-NEXT: [[TMP4:%.*]] = bitcast i8 [[TMP3]] to b8
-; BE-NEXT: ret b8 [[TMP4]]
+; BE-NEXT: [[TMP1:%.*]] = bitcast <4 x b8> [[X]] to b32
+; BE-NEXT: [[TMP2:%.*]] = bitextract b8, b32 [[TMP1]], i32 16
+; BE-NEXT: ret b8 [[TMP2]]
;
store <4 x b8> %x, ptr %p, align 4
%q = getelementptr i8, ptr %p, i64 1
@@ -230,20 +190,17 @@ define b32 @ptr_store_to_b32_load(ptr %p, ptr %x) {
; LE-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
; LE-NEXT: store ptr [[X]], ptr [[P]], align 8
; LE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 4
-; LE-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
-; LE-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 32
-; LE-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
-; LE-NEXT: [[TMP4:%.*]] = bitcast i32 [[TMP3]] to b32
-; LE-NEXT: ret b32 [[TMP4]]
+; LE-NEXT: [[TMP1:%.*]] = bitcast ptr [[X]] to b64
+; LE-NEXT: [[TMP2:%.*]] = bitextract b32, b64 [[TMP1]], i32 32
+; LE-NEXT: ret b32 [[TMP2]]
;
; BE-LABEL: define b32 @ptr_store_to_b32_load(
; BE-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
; BE-NEXT: store ptr [[X]], ptr [[P]], align 8
; BE-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P]], i64 4
-; BE-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
-; BE-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
-; BE-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to b32
-; BE-NEXT: ret b32 [[TMP3]]
+; BE-NEXT: [[TMP1:%.*]] = bitcast ptr [[X]] to b64
+; BE-NEXT: [[TMP2:%.*]] = bitextract b32, b64 [[TMP1]], i32 0
+; BE-NEXT: ret b32 [[TMP2]]
;
store ptr %x, ptr %p, align 8
%q = getelementptr i8, ptr %p, i64 4
@@ -255,9 +212,8 @@ define b64 @ptr_store_to_b64_load(ptr %p, ptr %x) {
; CHECK-LABEL: define b64 @ptr_store_to_b64_load(
; CHECK-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) {
; CHECK-NEXT: store ptr [[X]], ptr [[P]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64
-; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to b64
-; CHECK-NEXT: ret b64 [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast ptr [[X]] to b64
+; CHECK-NEXT: ret b64 [[TMP1]]
;
store ptr %x, ptr %p, align 8
%v = load b64, ptr %p, align 8
More information about the llvm-branch-commits
mailing list