summaryrefslogtreecommitdiff
path: root/llvm/test/Transforms/InstCombine/load-cmp.ll
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/InstCombine/load-cmp.ll')
-rw-r--r--llvm/test/Transforms/InstCombine/load-cmp.ll247
1 files changed, 245 insertions, 2 deletions
diff --git a/llvm/test/Transforms/InstCombine/load-cmp.ll b/llvm/test/Transforms/InstCombine/load-cmp.ll
index f44d27c691b5..10fe07295eed 100644
--- a/llvm/test/Transforms/InstCombine/load-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/load-cmp.ll
@@ -312,7 +312,7 @@ define i1 @test10_struct_arr_i16(i16 %x) {
define i1 @test10_struct_arr_i64(i64 %x) {
; CHECK-LABEL: @test10_struct_arr_i64(
-; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[TMP1:%.*]], 1
+; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[X:%.*]], 1
; CHECK-NEXT: ret i1 [[R]]
;
%p = getelementptr inbounds [4 x %Foo], ptr @GStructArr, i64 0, i64 %x, i32 2
@@ -361,7 +361,7 @@ define i1 @test10_struct_arr_noarrayty(i32 %x) {
define i1 @pr93017(i64 %idx) {
; CHECK-LABEL: @pr93017(
; CHECK-NEXT: [[TMP1:%.*]] = trunc nsw i64 [[IDX:%.*]] to i32
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @table, i32 0, i32 [[TMP1]]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds ptr, ptr @table, i32 [[TMP1]]
; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[GEP]], align 4
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[V]], null
; CHECK-NEXT: ret i1 [[CMP]]
@@ -371,3 +371,246 @@ define i1 @pr93017(i64 %idx) {
%cmp = icmp ne ptr %v, null
ret i1 %cmp
}
+
+@g_i32_lo = internal constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
+
+; Mask is 0b10101010
+define i1 @load_vs_array_type_mismatch1(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch1(
+; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1:%.*]]
+; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 170
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP3]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr inbounds i16, ptr @g_i32_lo, i32 %idx
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+@g_i32_hi = internal constant [4 x i32] [i32 u0x00010000, i32 u0x00020000, i32 u0x00030000, i32 u0x00040000]
+
+; Mask is 0b01010101
+define i1 @load_vs_array_type_mismatch2(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch2(
+; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1:%.*]]
+; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 85
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP3]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr inbounds i16, ptr @g_i32_hi, i32 %idx
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+@g_i16_1 = internal constant [8 x i16] [i16 0, i16 1, i16 1, i16 0, i16 0, i16 1, i16 1, i16 0]
+
+; idx == 1 || idx == 3
+define i1 @load_vs_array_type_mismatch_offset1(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch_offset1(
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr inbounds {i16, i16}, ptr @g_i16_1, i32 %idx, i32 1
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+define i1 @load_vs_array_type_mismatch_offset1_separate_gep(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch_offset1_separate_gep(
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep1 = getelementptr inbounds {i16, i16}, ptr @g_i16_1, i32 %idx
+ %gep2 = getelementptr inbounds i8, ptr %gep1, i32 2
+ %load = load i16, ptr %gep2
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+define i1 @load_vs_array_type_mismatch_offset1_separate_gep_swapped(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch_offset1_separate_gep_swapped(
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep1 = getelementptr inbounds i8, ptr @g_i16_1, i32 2
+ %gep2 = getelementptr inbounds {i16, i16}, ptr %gep1, i32 %idx
+ %load = load i16, ptr %gep2
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+@g_i16_2 = internal constant [8 x i16] [i16 1, i16 0, i16 0, i16 1, i16 1, i16 0, i16 0, i16 1]
+
+; idx == 0 || idx == 2
+define i1 @load_vs_array_type_mismatch_offset2(i32 %idx) {
+; CHECK-LABEL: @load_vs_array_type_mismatch_offset2(
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr inbounds {i16, i16}, ptr @g_i16_2, i32 %idx, i32 1
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+define i1 @offset_larger_than_stride(i32 %idx) {
+; CHECK-LABEL: @offset_larger_than_stride(
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr getelementptr inbounds nuw (i8, ptr @g_i16_1, i32 4), i32 [[IDX:%.*]]
+; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr [2 x i16], ptr @g_i16_1, i64 1, i32 %idx
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+define i1 @load_size_larger_stride(i32 %idx) {
+; CHECK-LABEL: @load_size_larger_stride(
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr @g_i16_1, i32 [[IDX:%.*]]
+; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep = getelementptr i8, ptr @g_i16_1, i32 %idx
+ %load = load i16, ptr %gep
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+@CG_MESSY = constant [9 x i32] [i32 1, i32 7, i32 -1, i32 5, i32 4, i32 1, i32 1, i32 5, i32 4]
+
+define i1 @cmp_load_constant_array_messy(i32 %x){
+; CHECK-LABEL: @cmp_load_constant_array_messy(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0:%.*]], 1073741823
+; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 373
+; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[TMP3]], 0
+; CHECK-NEXT: ret i1 [[COND]]
+;
+
+entry:
+ %isOK_ptr = getelementptr i32, ptr @CG_MESSY, i32 %x
+ %isOK = load i32, ptr %isOK_ptr
+ %cond = icmp slt i32 %isOK, 5
+ ret i1 %cond
+}
+
+define i1 @cmp_diff_load_constant_array_messy0(i32 %x){
+; CHECK-LABEL: @cmp_diff_load_constant_array_messy0(
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1:%.*]], 1073741823
+; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i32 1, [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 373
+; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[TMP4]], 0
+; CHECK-NEXT: ret i1 [[COND]]
+;
+ %isOK_ptr = getelementptr i32, ptr @CG_MESSY, i32 %x
+ %isOK = load i16, ptr %isOK_ptr
+ %cond = icmp slt i16 %isOK, 5
+ ret i1 %cond
+}
+
+; Load size larger than store size currently not supported.
+define i1 @cmp_diff_load_constant_array_messy1(i32 %x){
+; CHECK-LABEL: @cmp_diff_load_constant_array_messy1(
+; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr i6, ptr @CG_MESSY, i32 [[TMP1:%.*]]
+; CHECK-NEXT: [[ISOK:%.*]] = load i16, ptr [[ISOK_PTR]], align 2
+; CHECK-NEXT: [[COND:%.*]] = icmp slt i16 [[ISOK]], 5
+; CHECK-NEXT: ret i1 [[COND]]
+;
+ %isOK_ptr = getelementptr i6, ptr @CG_MESSY, i32 %x
+ %isOK = load i16, ptr %isOK_ptr
+ %cond = icmp slt i16 %isOK, 5
+ ret i1 %cond
+}
+
+define i1 @cmp_load_constant_array_variable_icmp(i32 %x, i32 %y) {
+; CHECK-LABEL: @cmp_load_constant_array_variable_icmp(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i32, ptr @CG_MESSY, i32 [[X:%.*]]
+; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
+; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], [[Y:%.*]]
+; CHECK-NEXT: ret i1 [[COND]]
+;
+entry:
+ %isOK_ptr = getelementptr inbounds i32, ptr @CG_MESSY, i32 %x
+ %isOK = load i32, ptr %isOK_ptr
+ %cond = icmp ult i32 %isOK, %y
+ ret i1 %cond
+}
+
+@CG_CLEAR = constant [10 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9]
+
+; Offsets not supported if negative or larger than stride.
+define i1 @cmp_load_constant_additional_positive_offset(i32 %x) {
+; CHECK-LABEL: @cmp_load_constant_additional_positive_offset(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds nuw (i8, ptr @CG_CLEAR, i32 20), i32 [[X:%.*]]
+; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
+; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
+; CHECK-NEXT: ret i1 [[COND]]
+;
+entry:
+ %isOK_ptr = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 5, i32 %x
+ %isOK = load i32, ptr %isOK_ptr
+ %cond = icmp ult i32 %isOK, 5
+ ret i1 %cond
+}
+
+define i1 @cmp_load_constant_additional_negative_offset(i32 %x) {
+; CHECK-LABEL: @cmp_load_constant_additional_negative_offset(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ISOK_PTR_SPLIT:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 [[X:%.*]]
+; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i8, ptr [[ISOK_PTR_SPLIT]], i32 -20
+; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
+; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
+; CHECK-NEXT: ret i1 [[COND]]
+;
+entry:
+ %isOK_ptr = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 %x, i32 -5
+ %isOK = load i32, ptr %isOK_ptr
+ %cond = icmp ult i32 %isOK, 5
+ ret i1 %cond
+}
+
+define i1 @cmp_load_multiple_indices(i32 %idx, i32 %idx2) {
+; CHECK-LABEL: @cmp_load_multiple_indices(
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i16, ptr @g_i16_1, i32 [[IDX:%.*]]
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i16, ptr [[GEP1]], i32 [[IDX2:%.*]]
+; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds nuw i8, ptr [[GEP2]], i32 2
+; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP3]], align 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep1 = getelementptr inbounds i16, ptr @g_i16_1, i32 %idx
+ %gep2 = getelementptr inbounds i16, ptr %gep1, i32 %idx2
+ %gep3 = getelementptr inbounds i8, ptr %gep2, i32 2
+ %load = load i16, ptr %gep3
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}
+
+define i1 @cmp_load_multiple_indices2(i32 %idx, i32 %idx2) {
+; CHECK-LABEL: @cmp_load_multiple_indices2(
+; CHECK-NEXT: [[GEP1_SPLIT:%.*]] = getelementptr inbounds [1 x i16], ptr @g_i16_1, i32 [[IDX:%.*]]
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i16, ptr [[GEP1_SPLIT]], i32 [[IDX2:%.*]]
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds nuw i8, ptr [[GEP1]], i32 2
+; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP2]], align 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %gep1 = getelementptr inbounds [1 x i16], ptr @g_i16_1, i32 %idx, i32 %idx2
+ %gep2 = getelementptr inbounds i8, ptr %gep1, i32 2
+ %load = load i16, ptr %gep2
+ %cmp = icmp eq i16 %load, 0
+ ret i1 %cmp
+}