The disjoint flag was recently added to IR in #72583 We already set it when we turn an add into an or. This patch sets it on Ors that weren't converted from an Add.
233 lines
8.4 KiB
LLVM
233 lines
8.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
|
|
|
|
;
|
|
; Tests for combining concat-able ops:
|
|
; or(zext(OP(x)), shl(zext(OP(y)),bw/2))
|
|
; -->
|
|
; OP(or(zext(x), shl(zext(y),bw/2)))
|
|
;
|
|
|
|
; BSWAP
|
|
|
|
; PR45715
|
|
define i64 @concat_bswap32_unary_split(i64 %a0) {
|
|
; CHECK-LABEL: @concat_bswap32_unary_split(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.bswap.i64(i64 [[A0:%.*]])
|
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
|
;
|
|
%1 = lshr i64 %a0, 32
|
|
%2 = trunc i64 %1 to i32
|
|
%3 = trunc i64 %a0 to i32
|
|
%4 = tail call i32 @llvm.bswap.i32(i32 %2)
|
|
%5 = tail call i32 @llvm.bswap.i32(i32 %3)
|
|
%6 = zext i32 %4 to i64
|
|
%7 = zext i32 %5 to i64
|
|
%8 = shl nuw i64 %7, 32
|
|
%9 = or i64 %6, %8
|
|
ret i64 %9
|
|
}
|
|
|
|
define <2 x i64> @concat_bswap32_unary_split_vector(<2 x i64> %a0) {
|
|
; CHECK-LABEL: @concat_bswap32_unary_split_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[A0:%.*]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP1]]
|
|
;
|
|
%1 = lshr <2 x i64> %a0, <i64 32, i64 32>
|
|
%2 = trunc <2 x i64> %1 to <2 x i32>
|
|
%3 = trunc <2 x i64> %a0 to <2 x i32>
|
|
%4 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %2)
|
|
%5 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %3)
|
|
%6 = zext <2 x i32> %4 to <2 x i64>
|
|
%7 = zext <2 x i32> %5 to <2 x i64>
|
|
%8 = shl nuw <2 x i64> %7, <i64 32, i64 32>
|
|
%9 = or <2 x i64> %6, %8
|
|
ret <2 x i64> %9
|
|
}
|
|
|
|
define i64 @concat_bswap32_unary_flip(i64 %a0) {
|
|
; CHECK-LABEL: @concat_bswap32_unary_flip(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.fshl.i64(i64 [[A0:%.*]], i64 [[A0]], i64 32)
|
|
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP1]])
|
|
; CHECK-NEXT: ret i64 [[TMP2]]
|
|
;
|
|
%1 = lshr i64 %a0, 32
|
|
%2 = trunc i64 %1 to i32
|
|
%3 = trunc i64 %a0 to i32
|
|
%4 = tail call i32 @llvm.bswap.i32(i32 %2)
|
|
%5 = tail call i32 @llvm.bswap.i32(i32 %3)
|
|
%6 = zext i32 %4 to i64
|
|
%7 = zext i32 %5 to i64
|
|
%8 = shl nuw i64 %6, 32
|
|
%9 = or i64 %7, %8
|
|
ret i64 %9
|
|
}
|
|
|
|
define <2 x i64> @concat_bswap32_unary_flip_vector(<2 x i64> %a0) {
|
|
; CHECK-LABEL: @concat_bswap32_unary_flip_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.fshl.v2i64(<2 x i64> [[A0:%.*]], <2 x i64> [[A0]], <2 x i64> <i64 32, i64 32>)
|
|
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[TMP1]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP2]]
|
|
;
|
|
%1 = lshr <2 x i64> %a0, <i64 32, i64 32>
|
|
%2 = trunc <2 x i64> %1 to <2 x i32>
|
|
%3 = trunc <2 x i64> %a0 to <2 x i32>
|
|
%4 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %2)
|
|
%5 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %3)
|
|
%6 = zext <2 x i32> %4 to <2 x i64>
|
|
%7 = zext <2 x i32> %5 to <2 x i64>
|
|
%8 = shl nuw <2 x i64> %6, <i64 32, i64 32>
|
|
%9 = or <2 x i64> %7, %8
|
|
ret <2 x i64> %9
|
|
}
|
|
|
|
define i64 @concat_bswap32_binary(i32 %a0, i32 %a1) {
|
|
; CHECK-LABEL: @concat_bswap32_binary(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[A1:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[A0:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 32
|
|
; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i64 [[TMP3]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP4]])
|
|
; CHECK-NEXT: ret i64 [[TMP5]]
|
|
;
|
|
%1 = tail call i32 @llvm.bswap.i32(i32 %a0)
|
|
%2 = tail call i32 @llvm.bswap.i32(i32 %a1)
|
|
%3 = zext i32 %1 to i64
|
|
%4 = zext i32 %2 to i64
|
|
%5 = shl nuw i64 %4, 32
|
|
%6 = or i64 %3, %5
|
|
ret i64 %6
|
|
}
|
|
|
|
define <2 x i64> @concat_bswap32_binary_vector(<2 x i32> %a0, <2 x i32> %a1) {
|
|
; CHECK-LABEL: @concat_bswap32_binary_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[A1:%.*]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[A0:%.*]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl nuw <2 x i64> [[TMP2]], <i64 32, i64 32>
|
|
; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i64> [[TMP3]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[TMP4]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP5]]
|
|
;
|
|
%1 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %a0)
|
|
%2 = tail call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %a1)
|
|
%3 = zext <2 x i32> %1 to <2 x i64>
|
|
%4 = zext <2 x i32> %2 to <2 x i64>
|
|
%5 = shl nuw <2 x i64> %4, <i64 32, i64 32>
|
|
%6 = or <2 x i64> %3, %5
|
|
ret <2 x i64> %6
|
|
}
|
|
|
|
declare i32 @llvm.bswap.i32(i32)
|
|
declare <2 x i32> @llvm.bswap.v2i32(<2 x i32>)
|
|
|
|
; BITREVERSE
|
|
|
|
define i64 @concat_bitreverse32_unary_split(i64 %a0) {
|
|
; CHECK-LABEL: @concat_bitreverse32_unary_split(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.bitreverse.i64(i64 [[A0:%.*]])
|
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
|
;
|
|
%1 = lshr i64 %a0, 32
|
|
%2 = trunc i64 %1 to i32
|
|
%3 = trunc i64 %a0 to i32
|
|
%4 = tail call i32 @llvm.bitreverse.i32(i32 %2)
|
|
%5 = tail call i32 @llvm.bitreverse.i32(i32 %3)
|
|
%6 = zext i32 %4 to i64
|
|
%7 = zext i32 %5 to i64
|
|
%8 = shl nuw i64 %7, 32
|
|
%9 = or i64 %6, %8
|
|
ret i64 %9
|
|
}
|
|
|
|
define <2 x i64> @concat_bitreverse32_unary_split_vector(<2 x i64> %a0) {
|
|
; CHECK-LABEL: @concat_bitreverse32_unary_split_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> [[A0:%.*]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP1]]
|
|
;
|
|
%1 = lshr <2 x i64> %a0, <i64 32, i64 32>
|
|
%2 = trunc <2 x i64> %1 to <2 x i32>
|
|
%3 = trunc <2 x i64> %a0 to <2 x i32>
|
|
%4 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %2)
|
|
%5 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %3)
|
|
%6 = zext <2 x i32> %4 to <2 x i64>
|
|
%7 = zext <2 x i32> %5 to <2 x i64>
|
|
%8 = shl nuw <2 x i64> %7, <i64 32, i64 32>
|
|
%9 = or <2 x i64> %6, %8
|
|
ret <2 x i64> %9
|
|
}
|
|
|
|
define i64 @concat_bitreverse32_unary_flip(i64 %a0) {
|
|
; CHECK-LABEL: @concat_bitreverse32_unary_flip(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.fshl.i64(i64 [[A0:%.*]], i64 [[A0]], i64 32)
|
|
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.bitreverse.i64(i64 [[TMP1]])
|
|
; CHECK-NEXT: ret i64 [[TMP2]]
|
|
;
|
|
%1 = lshr i64 %a0, 32
|
|
%2 = trunc i64 %1 to i32
|
|
%3 = trunc i64 %a0 to i32
|
|
%4 = tail call i32 @llvm.bitreverse.i32(i32 %2)
|
|
%5 = tail call i32 @llvm.bitreverse.i32(i32 %3)
|
|
%6 = zext i32 %4 to i64
|
|
%7 = zext i32 %5 to i64
|
|
%8 = shl nuw i64 %6, 32
|
|
%9 = or i64 %7, %8
|
|
ret i64 %9
|
|
}
|
|
|
|
define <2 x i64> @concat_bitreverse32_unary_flip_vector(<2 x i64> %a0) {
|
|
; CHECK-LABEL: @concat_bitreverse32_unary_flip_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.fshl.v2i64(<2 x i64> [[A0:%.*]], <2 x i64> [[A0]], <2 x i64> <i64 32, i64 32>)
|
|
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> [[TMP1]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP2]]
|
|
;
|
|
%1 = lshr <2 x i64> %a0, <i64 32, i64 32>
|
|
%2 = trunc <2 x i64> %1 to <2 x i32>
|
|
%3 = trunc <2 x i64> %a0 to <2 x i32>
|
|
%4 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %2)
|
|
%5 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %3)
|
|
%6 = zext <2 x i32> %4 to <2 x i64>
|
|
%7 = zext <2 x i32> %5 to <2 x i64>
|
|
%8 = shl nuw <2 x i64> %6, <i64 32, i64 32>
|
|
%9 = or <2 x i64> %7, %8
|
|
ret <2 x i64> %9
|
|
}
|
|
|
|
define i64 @concat_bitreverse32_binary(i32 %a0, i32 %a1) {
|
|
; CHECK-LABEL: @concat_bitreverse32_binary(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[A1:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[A0:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 32
|
|
; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i64 [[TMP3]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.bitreverse.i64(i64 [[TMP4]])
|
|
; CHECK-NEXT: ret i64 [[TMP5]]
|
|
;
|
|
%1 = tail call i32 @llvm.bitreverse.i32(i32 %a0)
|
|
%2 = tail call i32 @llvm.bitreverse.i32(i32 %a1)
|
|
%3 = zext i32 %1 to i64
|
|
%4 = zext i32 %2 to i64
|
|
%5 = shl nuw i64 %4, 32
|
|
%6 = or i64 %3, %5
|
|
ret i64 %6
|
|
}
|
|
|
|
define <2 x i64> @concat_bitreverse32_binary_vector(<2 x i32> %a0, <2 x i32> %a1) {
|
|
; CHECK-LABEL: @concat_bitreverse32_binary_vector(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[A1:%.*]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[A0:%.*]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl nuw <2 x i64> [[TMP2]], <i64 32, i64 32>
|
|
; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i64> [[TMP3]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> [[TMP4]])
|
|
; CHECK-NEXT: ret <2 x i64> [[TMP5]]
|
|
;
|
|
%1 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a0)
|
|
%2 = tail call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a1)
|
|
%3 = zext <2 x i32> %1 to <2 x i64>
|
|
%4 = zext <2 x i32> %2 to <2 x i64>
|
|
%5 = shl nuw <2 x i64> %4, <i64 32, i64 32>
|
|
%6 = or <2 x i64> %3, %5
|
|
ret <2 x i64> %6
|
|
}
|
|
|
|
declare i32 @llvm.bitreverse.i32(i32)
|
|
declare <2 x i32> @llvm.bitreverse.v2i32(<2 x i32>)
|