| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s | |
| define i8 @bitextract_out_of_range(b32 %x) { | |
| ; CHECK-LABEL: define i8 @bitextract_out_of_range( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret i8 poison | |
| ; | |
| %r = bitextract i8, b32 %x, i32 25 | |
| ret i8 %r | |
| } | |
| ; The last bit is in range. | |
| define i8 @neg_bitextract_in_range(b32 %x) { | |
| ; CHECK-LABEL: define i8 @neg_bitextract_in_range( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[R:%.*]] = bitextract i8, b32 [[X]], i32 24 | |
| ; CHECK-NEXT: ret i8 [[R]] | |
| ; | |
| %r = bitextract i8, b32 %x, i32 24 | |
| ret i8 %r | |
| } | |
| define ptr @bitextract_ptr_out_of_range(b64 %x) { | |
| ; CHECK-LABEL: define ptr @bitextract_ptr_out_of_range( | |
| ; CHECK-SAME: b64 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret ptr poison | |
| ; | |
| %r = bitextract ptr, b64 %x, i32 8 | |
| ret ptr %r | |
| } | |
| define ptr @bitextract_ptr_constant_out_of_range() { | |
| ; CHECK-LABEL: define ptr @bitextract_ptr_constant_out_of_range() { | |
| ; CHECK-NEXT: ret ptr poison | |
| ; | |
| %r = bitextract ptr, b64 1234605616436508552, i32 8 | |
| ret ptr %r | |
| } | |
| define b32 @bitinsert_out_of_range(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define b32 @bitinsert_out_of_range( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret b32 poison | |
| ; | |
| %r = bitinsert b32 %x, i8 %y, i32 25 | |
| ret b32 %r | |
| } | |
| ; The last bit is in range. | |
| define b32 @neg_bitinsert_in_range(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define b32 @neg_bitinsert_in_range( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[R:%.*]] = bitinsert b32 [[X]], i8 [[Y]], i32 24 | |
| ; CHECK-NEXT: ret b32 [[R]] | |
| ; | |
| %r = bitinsert b32 %x, i8 %y, i32 24 | |
| ret b32 %r | |
| } | |
| define b64 @bitinsert_ptr_out_of_range(b64 %x, ptr %p) { | |
| ; CHECK-LABEL: define b64 @bitinsert_ptr_out_of_range( | |
| ; CHECK-SAME: b64 [[X:%.*]], ptr [[P:%.*]]) { | |
| ; CHECK-NEXT: ret b64 poison | |
| ; | |
| %r = bitinsert b64 %x, ptr %p, i32 8 | |
| ret b64 %r | |
| } | |
| define i8 @bitextract_poison_offset(b32 %x) { | |
| ; CHECK-LABEL: define i8 @bitextract_poison_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret i8 poison | |
| ; | |
| %r = bitextract i8, b32 %x, i32 poison | |
| ret i8 %r | |
| } | |
| define i8 @bitextract_undef_offset(b32 %x) { | |
| ; CHECK-LABEL: define i8 @bitextract_undef_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret i8 poison | |
| ; | |
| %r = bitextract i8, b32 %x, i32 undef | |
| ret i8 %r | |
| } | |
| define b32 @bitinsert_poison_offset(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define b32 @bitinsert_poison_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret b32 poison | |
| ; | |
| %r = bitinsert b32 %x, i8 %y, i32 poison | |
| ret b32 %r | |
| } | |
| define b32 @bitinsert_undef_offset(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define b32 @bitinsert_undef_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret b32 poison | |
| ; | |
| %r = bitinsert b32 %x, i8 %y, i32 undef | |
| ret b32 %r | |
| } | |
| define b32 @bitextract_full_width(b32 %x) { | |
| ; CHECK-LABEL: define b32 @bitextract_full_width( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret b32 [[X]] | |
| ; | |
| %r = bitextract b32, b32 %x, i32 0 | |
| ret b32 %r | |
| } | |
| ; InstSimplify can't create a bitcast. | |
| define i32 @neg_bitextract_full_width_i32(b32 %x) { | |
| ; CHECK-LABEL: define i32 @neg_bitextract_full_width_i32( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[R:%.*]] = bitextract i32, b32 [[X]], i32 0 | |
| ; CHECK-NEXT: ret i32 [[R]] | |
| ; | |
| %r = bitextract i32, b32 %x, i32 0 | |
| ret i32 %r | |
| } | |
| define b32 @bitinsert_full_width(b32 %x, b32 %y) { | |
| ; CHECK-LABEL: define b32 @bitinsert_full_width( | |
| ; CHECK-SAME: b32 [[X:%.*]], b32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret b32 [[Y]] | |
| ; | |
| %r = bitinsert b32 %x, b32 %y, i32 0 | |
| ret b32 %r | |
| } | |
| ; InstSimplify can't create a bitcast. | |
| define b32 @neg_bitinsert_full_width_i32(b32 %x, i32 %y) { | |
| ; CHECK-LABEL: define b32 @neg_bitinsert_full_width_i32( | |
| ; CHECK-SAME: b32 [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[R:%.*]] = bitinsert b32 [[X]], i32 [[Y]], i32 0 | |
| ; CHECK-NEXT: ret b32 [[R]] | |
| ; | |
| %r = bitinsert b32 %x, i32 %y, i32 0 | |
| ret b32 %r | |
| } | |
| define i8 @bitextract_bitinsert_i8(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define i8 @bitextract_bitinsert_i8( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret i8 [[Y]] | |
| ; | |
| %i = bitinsert b32 %x, i8 %y, i32 8 | |
| %r = bitextract i8, b32 %i, i32 8 | |
| ret i8 %r | |
| } | |
| define b8 @bitextract_bitinsert_b8(b32 %x, b8 %y) { | |
| ; CHECK-LABEL: define b8 @bitextract_bitinsert_b8( | |
| ; CHECK-SAME: b32 [[X:%.*]], b8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret b8 [[Y]] | |
| ; | |
| %i = bitinsert b32 %x, b8 %y, i32 8 | |
| %r = bitextract b8, b32 %i, i32 8 | |
| ret b8 %r | |
| } | |
| define float @bitextract_bitinsert_float(b64 %x, float %y) { | |
| ; CHECK-LABEL: define float @bitextract_bitinsert_float( | |
| ; CHECK-SAME: b64 [[X:%.*]], float [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret float [[Y]] | |
| ; | |
| %i = bitinsert b64 %x, float %y, i32 32 | |
| %r = bitextract float, b64 %i, i32 32 | |
| ret float %r | |
| } | |
| define ptr @bitextract_bitinsert_ptr(b128 %x, ptr %y) { | |
| ; CHECK-LABEL: define ptr @bitextract_bitinsert_ptr( | |
| ; CHECK-SAME: b128 [[X:%.*]], ptr [[Y:%.*]]) { | |
| ; CHECK-NEXT: ret ptr [[Y]] | |
| ; | |
| %i = bitinsert b128 %x, ptr %y, i32 64 | |
| %r = bitextract ptr, b128 %i, i32 64 | |
| ret ptr %r | |
| } | |
| define i8 @bitextract_bitinsert_variable_offset(b32 %x, i8 %y, i32 %n) { | |
| ; CHECK-LABEL: define i8 @bitextract_bitinsert_variable_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]], i32 [[N:%.*]]) { | |
| ; CHECK-NEXT: ret i8 [[Y]] | |
| ; | |
| %i = bitinsert b32 %x, i8 %y, i32 %n | |
| %r = bitextract i8, b32 %i, i32 %n | |
| ret i8 %r | |
| } | |
| ; The offsets differ. | |
| define i8 @neg_bitextract_bitinsert_other_offset(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define i8 @neg_bitextract_bitinsert_other_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[I:%.*]] = bitinsert b32 [[X]], i8 [[Y]], i32 8 | |
| ; CHECK-NEXT: [[R:%.*]] = bitextract i8, b32 [[I]], i32 16 | |
| ; CHECK-NEXT: ret i8 [[R]] | |
| ; | |
| %i = bitinsert b32 %x, i8 %y, i32 8 | |
| %r = bitextract i8, b32 %i, i32 16 | |
| ret i8 %r | |
| } | |
| ; The types differ. | |
| define b8 @neg_bitextract_bitinsert_other_type(b32 %x, i8 %y) { | |
| ; CHECK-LABEL: define b8 @neg_bitextract_bitinsert_other_type( | |
| ; CHECK-SAME: b32 [[X:%.*]], i8 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[I:%.*]] = bitinsert b32 [[X]], i8 [[Y]], i32 8 | |
| ; CHECK-NEXT: [[R:%.*]] = bitextract b8, b32 [[I]], i32 8 | |
| ; CHECK-NEXT: ret b8 [[R]] | |
| ; | |
| %i = bitinsert b32 %x, i8 %y, i32 8 | |
| %r = bitextract b8, b32 %i, i32 8 | |
| ret b8 %r | |
| } | |
| define b32 @bitinsert_bitextract_b8(b32 %x) { | |
| ; CHECK-LABEL: define b32 @bitinsert_bitextract_b8( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret b32 [[X]] | |
| ; | |
| %e = bitextract b8, b32 %x, i32 8 | |
| %r = bitinsert b32 %x, b8 %e, i32 8 | |
| ret b32 %r | |
| } | |
| define b32 @bitinsert_bitextract_variable_offset(b32 %x, i32 %n) { | |
| ; CHECK-LABEL: define b32 @bitinsert_bitextract_variable_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]], i32 [[N:%.*]]) { | |
| ; CHECK-NEXT: ret b32 [[X]] | |
| ; | |
| %e = bitextract b8, b32 %x, i32 %n | |
| %r = bitinsert b32 %x, b8 %e, i32 %n | |
| ret b32 %r | |
| } | |
| define b32 @bitinsert_bitextract_i8(b32 %x) { | |
| ; CHECK-LABEL: define b32 @bitinsert_bitextract_i8( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret b32 [[X]] | |
| ; | |
| %e = bitextract i8, b32 %x, i32 8 | |
| %r = bitinsert b32 %x, i8 %e, i32 8 | |
| ret b32 %r | |
| } | |
| define b64 @bitinsert_bitextract_double(b64 %x) { | |
| ; CHECK-LABEL: define b64 @bitinsert_bitextract_double( | |
| ; CHECK-SAME: b64 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret b64 [[X]] | |
| ; | |
| %e = bitextract double, b64 %x, i32 0 | |
| %r = bitinsert b64 %x, double %e, i32 0 | |
| ret b64 %r | |
| } | |
| define b64 @bitinsert_bitextract_ptr(b64 %x) { | |
| ; CHECK-LABEL: define b64 @bitinsert_bitextract_ptr( | |
| ; CHECK-SAME: b64 [[X:%.*]]) { | |
| ; CHECK-NEXT: ret b64 [[X]] | |
| ; | |
| %e = bitextract ptr, b64 %x, i32 0 | |
| %r = bitinsert b64 %x, ptr %e, i32 0 | |
| ret b64 %r | |
| } | |
| ; The bases differ. | |
| define b32 @neg_bitinsert_bitextract_other_base(b32 %x, b32 %y) { | |
| ; CHECK-LABEL: define b32 @neg_bitinsert_bitextract_other_base( | |
| ; CHECK-SAME: b32 [[X:%.*]], b32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[E:%.*]] = bitextract b8, b32 [[Y]], i32 8 | |
| ; CHECK-NEXT: [[R:%.*]] = bitinsert b32 [[X]], b8 [[E]], i32 8 | |
| ; CHECK-NEXT: ret b32 [[R]] | |
| ; | |
| %e = bitextract b8, b32 %y, i32 8 | |
| %r = bitinsert b32 %x, b8 %e, i32 8 | |
| ret b32 %r | |
| } | |
| ; The offsets differ. | |
| define b32 @neg_bitinsert_bitextract_other_offset(b32 %x) { | |
| ; CHECK-LABEL: define b32 @neg_bitinsert_bitextract_other_offset( | |
| ; CHECK-SAME: b32 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[E:%.*]] = bitextract b8, b32 [[X]], i32 8 | |
| ; CHECK-NEXT: [[R:%.*]] = bitinsert b32 [[X]], b8 [[E]], i32 16 | |
| ; CHECK-NEXT: ret b32 [[R]] | |
| ; | |
| %e = bitextract b8, b32 %x, i32 8 | |
| %r = bitinsert b32 %x, b8 %e, i32 16 | |
| ret b32 %r | |
| } |