154 lines
5.1 KiB
LLVM
154 lines
5.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -reassociate -S | FileCheck %s
|
|
|
|
; Basic pattern where two contiguous i8 loads form a wider i16 load
|
|
define i16 @p0_i8_i8_i16(i8* %ptr) {
|
|
; CHECK-LABEL: @p0_i8_i8_i16(
|
|
; CHECK-NEXT: [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[I2:%.*]] = load i8, i8* [[I]], align 1
|
|
; CHECK-NEXT: [[I3:%.*]] = zext i8 [[I2]] to i16
|
|
; CHECK-NEXT: [[I4:%.*]] = shl i16 [[I3]], 8
|
|
; CHECK-NEXT: [[I5:%.*]] = load i8, i8* [[PTR]], align 1
|
|
; CHECK-NEXT: [[I6:%.*]] = zext i8 [[I5]] to i16
|
|
; CHECK-NEXT: [[I7:%.*]] = or i16 [[I4]], [[I6]]
|
|
; CHECK-NEXT: [[I8:%.*]] = add i16 [[I7]], 42
|
|
; CHECK-NEXT: ret i16 [[I8]]
|
|
;
|
|
%i = getelementptr inbounds i8, i8* %ptr, i64 1
|
|
%i2 = load i8, i8* %i
|
|
%i3 = zext i8 %i2 to i16
|
|
%i4 = shl i16 %i3, 8
|
|
%i5 = load i8, i8* %ptr
|
|
%i6 = zext i8 %i5 to i16
|
|
%i7 = or i16 %i4, %i6
|
|
%i8 = add i16 %i7, 42
|
|
ret i16 %i8
|
|
}
|
|
|
|
; Basic pattern where two contiguous i8 loads form a wider i16 load, with swapped endianness
|
|
define i16 @p1_i8_i8_i16_swapped(i8* %ptr) {
|
|
; CHECK-LABEL: @p1_i8_i8_i16_swapped(
|
|
; CHECK-NEXT: [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
|
|
; CHECK-NEXT: [[I2:%.*]] = zext i8 [[I]] to i16
|
|
; CHECK-NEXT: [[I3:%.*]] = shl i16 [[I2]], 8
|
|
; CHECK-NEXT: [[I4:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 1
|
|
; CHECK-NEXT: [[I5:%.*]] = load i8, i8* [[I4]], align 1
|
|
; CHECK-NEXT: [[I6:%.*]] = zext i8 [[I5]] to i16
|
|
; CHECK-NEXT: [[I7:%.*]] = or i16 [[I3]], [[I6]]
|
|
; CHECK-NEXT: [[I8:%.*]] = add i16 [[I7]], 42
|
|
; CHECK-NEXT: ret i16 [[I8]]
|
|
;
|
|
%i = load i8, i8* %ptr
|
|
%i2 = zext i8 %i to i16
|
|
%i3 = shl i16 %i2, 8
|
|
%i4 = getelementptr inbounds i8, i8* %ptr, i64 1
|
|
%i5 = load i8, i8* %i4
|
|
%i6 = zext i8 %i5 to i16
|
|
%i7 = or i16 %i3, %i6
|
|
%i8 = add i16 %i7, 42
|
|
ret i16 %i8
|
|
}
|
|
|
|
; Loads are spaced out by a bit, but we don't check for that.
|
|
define i16 @p2(i8* %ptr) {
|
|
; CHECK-LABEL: @p2(
|
|
; CHECK-NEXT: [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[I2:%.*]] = load i8, i8* [[I]], align 1
|
|
; CHECK-NEXT: [[I3:%.*]] = zext i8 [[I2]] to i16
|
|
; CHECK-NEXT: [[I4:%.*]] = shl i16 [[I3]], 9
|
|
; CHECK-NEXT: [[I5:%.*]] = load i8, i8* [[PTR]], align 1
|
|
; CHECK-NEXT: [[I6:%.*]] = zext i8 [[I5]] to i16
|
|
; CHECK-NEXT: [[I7:%.*]] = or i16 [[I4]], [[I6]]
|
|
; CHECK-NEXT: [[I8:%.*]] = add i16 [[I7]], 42
|
|
; CHECK-NEXT: ret i16 [[I8]]
|
|
;
|
|
%i = getelementptr inbounds i8, i8* %ptr, i64 1
|
|
%i2 = load i8, i8* %i
|
|
%i3 = zext i8 %i2 to i16
|
|
%i4 = shl i16 %i3, 9 ; wrong shift amount
|
|
%i5 = load i8, i8* %ptr
|
|
%i6 = zext i8 %i5 to i16
|
|
%i7 = or i16 %i4, %i6
|
|
%i8 = add i16 %i7, 42
|
|
ret i16 %i8
|
|
}
|
|
|
|
; Both bytes are the same, but we don't check for that.
|
|
define i16 @p3(i8* %ptr) {
|
|
; CHECK-LABEL: @p3(
|
|
; CHECK-NEXT: [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
|
|
; CHECK-NEXT: [[I2:%.*]] = zext i8 [[I]] to i16
|
|
; CHECK-NEXT: [[I3:%.*]] = shl i16 [[I2]], 8
|
|
; CHECK-NEXT: [[I4:%.*]] = or i16 [[I3]], [[I2]]
|
|
; CHECK-NEXT: [[I5:%.*]] = add i16 [[I4]], 42
|
|
; CHECK-NEXT: ret i16 [[I5]]
|
|
;
|
|
%i = load i8, i8* %ptr
|
|
%i2 = zext i8 %i to i16
|
|
%i3 = shl i16 %i2, 8
|
|
%i4 = or i16 %i3, %i2
|
|
%i5 = add i16 %i4, 42
|
|
ret i16 %i5
|
|
}
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
; Negative tests, should be transformed.
|
|
|
|
; Low bits are not a load
|
|
define i16 @n4(i8* %ptr) {
|
|
; CHECK-LABEL: @n4(
|
|
; CHECK-NEXT: [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
|
|
; CHECK-NEXT: [[I2:%.*]] = zext i8 [[I]] to i16
|
|
; CHECK-NEXT: [[I3:%.*]] = shl i16 [[I2]], 8
|
|
; CHECK-NEXT: [[I5:%.*]] = add i16 [[I3]], 84
|
|
; CHECK-NEXT: ret i16 [[I5]]
|
|
;
|
|
%i = load i8, i8* %ptr
|
|
%i2 = zext i8 %i to i16
|
|
%i3 = shl i16 %i2, 8
|
|
%i4 = or i16 %i3, 42 ; Second operand is bad
|
|
%i5 = add i16 %i4, 42
|
|
ret i16 %i5
|
|
}
|
|
|
|
; Low bits are not a load
|
|
define i16 @n5(i8* %ptr, i8 %lowbits) {
|
|
; CHECK-LABEL: @n5(
|
|
; CHECK-NEXT: [[I:%.*]] = load i8, i8* [[PTR:%.*]], align 1
|
|
; CHECK-NEXT: [[I2:%.*]] = zext i8 [[I]] to i16
|
|
; CHECK-NEXT: [[I3:%.*]] = shl i16 [[I2]], 8
|
|
; CHECK-NEXT: [[I4:%.*]] = zext i8 [[LOWBITS:%.*]] to i16
|
|
; CHECK-NEXT: [[I5:%.*]] = add i16 [[I4]], 42
|
|
; CHECK-NEXT: [[I6:%.*]] = add i16 [[I5]], [[I3]]
|
|
; CHECK-NEXT: ret i16 [[I6]]
|
|
;
|
|
%i = load i8, i8* %ptr
|
|
%i2 = zext i8 %i to i16
|
|
%i3 = shl i16 %i2, 8
|
|
%i4 = zext i8 %lowbits to i16 ; base operand is bad
|
|
%i5 = or i16 %i3, %i4
|
|
%i6 = add i16 %i5, 42
|
|
ret i16 %i6
|
|
}
|
|
|
|
; High bits are not a load
|
|
define i16 @n6(i8* %ptr, i8 %highbits) {
|
|
; CHECK-LABEL: @n6(
|
|
; CHECK-NEXT: [[I:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[I4:%.*]] = shl i16 42, 8
|
|
; CHECK-NEXT: [[I5:%.*]] = load i8, i8* [[PTR]], align 1
|
|
; CHECK-NEXT: [[I6:%.*]] = zext i8 [[I5]] to i16
|
|
; CHECK-NEXT: [[I7:%.*]] = add i16 [[I4]], 42
|
|
; CHECK-NEXT: [[I8:%.*]] = add i16 [[I7]], [[I6]]
|
|
; CHECK-NEXT: ret i16 [[I8]]
|
|
;
|
|
%i = getelementptr inbounds i8, i8* %ptr, i64 1
|
|
%i2 = load i8, i8* %i
|
|
%i4 = shl i16 42, 8 ; base operand is bad
|
|
%i5 = load i8, i8* %ptr
|
|
%i6 = zext i8 %i5 to i16
|
|
%i7 = or i16 %i4, %i6
|
|
%i8 = add i16 %i7, 42
|
|
ret i16 %i8
|
|
}
|