| ; 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:%.*]] = 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:%.*]] = 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 | |
| %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:%.*]] = 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:%.*]] = 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 | |
| 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:%.*]] = 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:%.*]] = 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 | |
| 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 ptr | |
| ; CHECK-NEXT: ret ptr [[TMP1]] | |
| ; | |
| 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:%.*]] = 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:%.*]] = 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 | |
| %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:%.*]] = 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:%.*]] = 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 | |
| %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:%.*]] = 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:%.*]] = 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 | |
| %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:%.*]] = 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:%.*]] = bitextract b8, b32 [[A]], i32 16 | |
| ; BE-NEXT: ret b8 [[TMP1]] | |
| ; | |
| %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 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 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 | |
| %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:%.*]] = 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:%.*]] = 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 | |
| %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:%.*]] = bitcast ptr [[X]] to b64 | |
| ; CHECK-NEXT: ret b64 [[TMP1]] | |
| ; | |
| 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 | |
| } |