CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
359 lines
12 KiB
LLVM
359 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
; Test case: Fold (X << 5) == ((Y << 5) + 32) into X == (Y + 1).
|
|
; This corresponds to the provided alive2 proof.
|
|
|
|
declare void @use_i64(i64)
|
|
|
|
define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_base(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 32
|
|
%v6 = icmp eq i64 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: icmp ne
|
|
define i1 @shl_add_const_ne(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_ne(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 32
|
|
%v6 = icmp ne i64 %v1, %v5 ; Note: icmp ne
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: shl amounts do not match (5 vs 4).
|
|
define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_mismatch_shl_amt(
|
|
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5
|
|
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 4
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 16
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
%v4 = shl nsw i64 %v3, 4 ; Shift amount mismatch
|
|
%v5 = add nsw i64 %v4, 16
|
|
%v6 = icmp eq i64 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Constant K is a multiple of 2^L (64 vs 32). Should simplify to K/2^L = 2.
|
|
define i1 @shl_add_const_eq_k_multiple_of_pow2(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_k_multiple_of_pow2(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 2
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 64 ; Constant mismatch
|
|
%v6 = icmp eq i64 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Missing NSW flag on one of the shl instructions.
|
|
define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_no_nsw_on_v1(
|
|
; CHECK-NEXT: [[V1:%.*]] = shl i64 [[V0:%.*]], 5
|
|
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl i64 %v0, 5 ; Missing nsw
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 32
|
|
%v6 = icmp eq i64 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Lower bit width (i8) and different shift amount (3). Constant is 8.
|
|
define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_i8(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 [[V0:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i8 %v0, 3
|
|
%v4 = shl nsw i8 %v3, 3
|
|
%v5 = add nsw i8 %v4, 8 ; 2^3 = 8
|
|
%v6 = icmp eq i8 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: i32 bit width and larger shift amount (10). Constant is 1024.
|
|
define i1 @shl_add_const_eq_i32(i32 %v0, i32 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_i32(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 [[V0:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i32 %v0, 10
|
|
%v4 = shl nsw i32 %v3, 10
|
|
%v5 = add nsw i32 %v4, 1024 ; 2^10 = 1024
|
|
%v6 = icmp eq i32 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Multi-use case. The optimization should still occur if applicable,
|
|
; but the extraneous call must be preserved.
|
|
define i1 @shl_add_const_eq_multi_use(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_multi_use(
|
|
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5
|
|
; CHECK-NEXT: call void @use_i64(i64 [[V1]])
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V0]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
call void @use_i64(i64 %v1) ; Additional use of v1
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 32
|
|
%v6 = icmp eq i64 %v1, %v5
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Vector splat. Should fold once optimization is applied.
|
|
define <2 x i1> @shl_add_const_eq_vec_splat(<2 x i64> %v0, <2 x i64> %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_vec_splat(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V3:%.*]], splat (i64 1)
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret <2 x i1> [[V6]]
|
|
;
|
|
%v1 = shl nsw <2 x i64> %v0, <i64 5, i64 5>
|
|
%v4 = shl nsw <2 x i64> %v3, <i64 5, i64 5>
|
|
%v5 = add nsw <2 x i64> %v4, <i64 32, i64 32>
|
|
%v6 = icmp eq <2 x i64> %v1, %v5
|
|
ret <2 x i1> %v6
|
|
}
|
|
|
|
; Test: Vector splat with poison. Should fold once optimization is applied.
|
|
define <2 x i1> @shl_add_const_eq_vec_splat_poison(<2 x i64> %v0, <2 x i64> %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_vec_splat_poison(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V3:%.*]], <i64 1, i64 poison>
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret <2 x i1> [[V6]]
|
|
;
|
|
%v1 = shl nsw <2 x i64> %v0, <i64 5, i64 5>
|
|
%v4 = shl nsw <2 x i64> %v3, <i64 5, i64 5>
|
|
%v5 = add nsw <2 x i64> %v4, <i64 32, i64 poison>
|
|
%v6 = icmp eq <2 x i64> %v1, %v5
|
|
ret <2 x i1> %v6
|
|
}
|
|
|
|
; Test: Vector non-splat (should not fold).
|
|
define <2 x i1> @shl_add_const_eq_vec_non_splat(<2 x i64> %v0, <2 x i64> %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_vec_non_splat(
|
|
; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], <i64 5, i64 6>
|
|
; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], <i64 5, i64 6>
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], <i64 32, i64 64>
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]]
|
|
; CHECK-NEXT: ret <2 x i1> [[V6]]
|
|
;
|
|
%v1 = shl nsw <2 x i64> %v0, <i64 5, i64 6>
|
|
%v4 = shl nsw <2 x i64> %v3, <i64 5, i64 6>
|
|
%v5 = add nsw <2 x i64> %v4, <i64 32, i64 64>
|
|
%v6 = icmp eq <2 x i64> %v1, %v5
|
|
ret <2 x i1> %v6
|
|
}
|
|
|
|
; Test: Commutative (shl on the right side).
|
|
define i1 @shl_add_const_eq_commutative(i64 %v0, i64 %v3) {
|
|
; CHECK-LABEL: @shl_add_const_eq_commutative(
|
|
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
|
|
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V0:%.*]], [[V5]]
|
|
; CHECK-NEXT: ret i1 [[V6]]
|
|
;
|
|
%v1 = shl nsw i64 %v0, 5
|
|
%v4 = shl nsw i64 %v3, 5
|
|
%v5 = add nsw i64 %v4, 32
|
|
%v6 = icmp eq i64 %v5, %v1
|
|
ret i1 %v6
|
|
}
|
|
|
|
; Test: Variable shift amount with nuw (Logical)
|
|
define i1 @icmp_shl_var_amount_nuw(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_var_amount_nuw(
|
|
; CHECK-NEXT: [[Y:%.*]] = add nuw i32 [[Y1:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nuw i32 %x, 5
|
|
%shly = shl nuw i32 %y, 5
|
|
%add = add nuw i32 %shly, 32
|
|
%cmp = icmp eq i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: Variable shift amount with nsw (Arithmetic)
|
|
define i1 @icmp_shl_var_amount_nsw(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_var_amount_nsw(
|
|
; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[Y1:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nsw i32 %x, 5
|
|
%shly = shl nsw i32 %y, 5
|
|
%add = add nsw i32 %shly, 32
|
|
%cmp = icmp eq i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: ult (Unsigned Less Than) with nuw
|
|
define i1 @icmp_shl_nuw_ult(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_nuw_ult(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nuw i32 %x, 5
|
|
%shly = shl nuw i32 %y, 5
|
|
%add = add nuw i32 %shly, 32
|
|
%cmp = icmp ult i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: ugt (Unsigned Greater Than) with nuw
|
|
define i1 @icmp_shl_nuw_ugt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_nuw_ugt(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nuw i32 %x, 5
|
|
%shly = shl nuw i32 %y, 5
|
|
%add = add nuw i32 %shly, 32
|
|
%cmp = icmp ugt i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: slt (Signed Less Than) with nsw
|
|
define i1 @icmp_shl_nsw_slt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_nsw_slt(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nsw i32 %x, 5
|
|
%shly = shl nsw i32 %y, 5
|
|
%add = add nsw i32 %shly, 32
|
|
%cmp = icmp slt i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: sgt (Signed Greater Than) with nsw
|
|
define i1 @icmp_shl_nsw_sgt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_nsw_sgt(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nsw i32 %x, 5
|
|
%shly = shl nsw i32 %y, 5
|
|
%add = add nsw i32 %shly, 32
|
|
%cmp = icmp sgt i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Test: sle (Signed Less or Equal) with nsw
|
|
define i1 @icmp_shl_nsw_sle(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_shl_nsw_sle(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nsw i32 %x, 5
|
|
%shly = shl nsw i32 %y, 5
|
|
%add = add nsw i32 %shly, 32
|
|
%cmp = icmp sle i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; NOTE: This is a regression test for a miscompile discovered by fuzzing.
|
|
define i1 @icmp_slt_shl_nsw_add_nsw_fuzz(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_slt_shl_nsw_add_nsw_fuzz(
|
|
; CHECK-NEXT: [[SHLX:%.*]] = shl nsw i32 [[X:%.*]], 5
|
|
; CHECK-NEXT: [[SHLY:%.*]] = shl nuw i32 [[Y:%.*]], 5
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[SHLX]], [[SHLY]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nsw i32 %x, 5
|
|
%shly = shl nuw i32 %y, 5
|
|
%add = add nsw i32 32, %shly
|
|
%cmp = icmp slt i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; NOTE: This is a regression test for a miscompile discovered by fuzzing (unsigned comparison).
|
|
define i1 @icmp_ugt_shl_nuw_add_nsw_fuzz(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @icmp_ugt_shl_nuw_add_nsw_fuzz(
|
|
; CHECK-NEXT: [[SHLX:%.*]] = shl nuw i32 [[X:%.*]], 5
|
|
; CHECK-NEXT: [[SHLY:%.*]] = shl nsw i32 [[Y:%.*]], 5
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SHLY]], 32
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[SHLX]], [[ADD]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shlx = shl nuw i32 %x, 5
|
|
%shly = shl nsw i32 %y, 5
|
|
%add = add nsw i32 %shly, 32
|
|
%cmp = icmp ugt i32 %shlx, %add
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Regression test: (shl nuw X, C1) `icmp` (lshr Y, C2) must NOT fold into
|
|
; X `icmp` (lshr Y, C1+C2), because lshr is lossy and the low C1 bits of
|
|
; (lshr Y, C2) may be non-zero.
|
|
;
|
|
; Counterexample: X=1, Y=34, C1=4, C2=1
|
|
; Correct: (1 << 4) uge (34 >> 1) = 16 uge 17 = false
|
|
; Buggy: 1 uge (34 >> 5) = 1 uge 1 = true <-- WRONG
|
|
define i1 @test_uge_shl_nuw_lshr(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: @test_uge_shl_nuw_lshr(
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X:%.*]], 4
|
|
; CHECK-NEXT: [[LSHR:%.*]] = lshr i64 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i64 [[SHL]], [[LSHR]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shl = shl nuw i64 %x, 4
|
|
%lshr = lshr i64 %y, 1
|
|
%cmp = icmp uge i64 %shl, %lshr
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @test_ult_shl_nuw_lshr(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: @test_ult_shl_nuw_lshr(
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X:%.*]], 4
|
|
; CHECK-NEXT: [[LSHR:%.*]] = lshr i64 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], [[LSHR]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shl = shl nuw i64 %x, 4
|
|
%lshr = lshr i64 %y, 1
|
|
%cmp = icmp ult i64 %shl, %lshr
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Same pattern with eq predicate: also must not fold.
|
|
define i1 @test_eq_shl_nuw_lshr(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: @test_eq_shl_nuw_lshr(
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X:%.*]], 4
|
|
; CHECK-NEXT: [[LSHR:%.*]] = lshr i64 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[SHL]], [[LSHR]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shl = shl nuw i64 %x, 4
|
|
%lshr = lshr i64 %y, 1
|
|
%cmp = icmp eq i64 %shl, %lshr
|
|
ret i1 %cmp
|
|
}
|