@@ -371,3 +371,186 @@ define i1 @pr93017(i64 %idx) {
371371 %cmp = icmp ne ptr %v , null
372372 ret i1 %cmp
373373}
374+
375+ @g_i32_lo = internal constant [4 x i32 ] [i32 1 , i32 2 , i32 3 , i32 4 ]
376+
377+ ; Mask is 0b10101010
378+ define i1 @load_vs_array_type_mismatch1 (i32 %idx ) {
379+ ; CHECK-LABEL: @load_vs_array_type_mismatch1(
380+ ; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1:%.*]]
381+ ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 170
382+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP3]], 0
383+ ; CHECK-NEXT: ret i1 [[CMP]]
384+ ;
385+ %gep = getelementptr inbounds i16 , ptr @g_i32_lo , i32 %idx
386+ %load = load i16 , ptr %gep
387+ %cmp = icmp eq i16 %load , 0
388+ ret i1 %cmp
389+ }
390+
391+ @g_i32_hi = internal constant [4 x i32 ] [i32 u0x00010000, i32 u0x00020000, i32 u0x00030000, i32 u0x00040000]
392+
393+ ; Mask is 0b01010101
394+ define i1 @load_vs_array_type_mismatch2 (i32 %idx ) {
395+ ; CHECK-LABEL: @load_vs_array_type_mismatch2(
396+ ; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1:%.*]]
397+ ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 85
398+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP3]], 0
399+ ; CHECK-NEXT: ret i1 [[CMP]]
400+ ;
401+ %gep = getelementptr inbounds i16 , ptr @g_i32_hi , i32 %idx
402+ %load = load i16 , ptr %gep
403+ %cmp = icmp eq i16 %load , 0
404+ ret i1 %cmp
405+ }
406+
407+ @g_i16_1 = internal constant [8 x i16 ] [i16 0 , i16 1 , i16 1 , i16 0 , i16 0 , i16 1 , i16 1 , i16 0 ]
408+
409+ ; idx == 1 || idx == 3
410+ define i1 @load_vs_array_type_mismatch_offset1 (i32 %idx ) {
411+ ; CHECK-LABEL: @load_vs_array_type_mismatch_offset1(
412+ ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
413+ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
414+ ; CHECK-NEXT: ret i1 [[CMP]]
415+ ;
416+ %gep = getelementptr inbounds {i16 , i16 }, ptr @g_i16_1 , i32 %idx , i32 1
417+ %load = load i16 , ptr %gep
418+ %cmp = icmp eq i16 %load , 0
419+ ret i1 %cmp
420+ }
421+
422+ @g_i16_2 = internal constant [8 x i16 ] [i16 1 , i16 0 , i16 0 , i16 1 , i16 1 , i16 0 , i16 0 , i16 1 ]
423+
424+ ; idx == 0 || idx == 2
425+ define i1 @load_vs_array_type_mismatch_offset2 (i32 %idx ) {
426+ ; CHECK-LABEL: @load_vs_array_type_mismatch_offset2(
427+ ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IDX:%.*]], -3
428+ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
429+ ; CHECK-NEXT: ret i1 [[CMP]]
430+ ;
431+ %gep = getelementptr inbounds {i16 , i16 }, ptr @g_i16_2 , i32 %idx , i32 1
432+ %load = load i16 , ptr %gep
433+ %cmp = icmp eq i16 %load , 0
434+ ret i1 %cmp
435+ }
436+
437+ define i1 @offset_larger_than_stride (i32 %idx ) {
438+ ; CHECK-LABEL: @offset_larger_than_stride(
439+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr [2 x i16], ptr @g_i16_1, i32 1, i32 [[TMP1:%.*]]
440+ ; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
441+ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
442+ ; CHECK-NEXT: ret i1 [[CMP]]
443+ ;
444+ %gep = getelementptr [2 x i16 ], ptr @g_i16_1 , i64 1 , i32 %idx
445+ %load = load i16 , ptr %gep
446+ %cmp = icmp eq i16 %load , 0
447+ ret i1 %cmp
448+ }
449+
450+ define i1 @load_size_larger_stride (i32 %idx ) {
451+ ; CHECK-LABEL: @load_size_larger_stride(
452+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr @g_i16_1, i32 [[IDX:%.*]]
453+ ; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
454+ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
455+ ; CHECK-NEXT: ret i1 [[CMP]]
456+ ;
457+ %gep = getelementptr i8 , ptr @g_i16_1 , i32 %idx
458+ %load = load i16 , ptr %gep
459+ %cmp = icmp eq i16 %load , 0
460+ ret i1 %cmp
461+ }
462+
463+ @CG_MESSY = constant [9 x i32 ] [i32 1 , i32 7 , i32 -1 , i32 5 , i32 4 , i32 1 , i32 1 , i32 5 , i32 4 ]
464+
465+ define i1 @cmp_load_constant_array_messy (i32 %x ){
466+ ; CHECK-LABEL: @cmp_load_constant_array_messy(
467+ ; CHECK-NEXT: entry:
468+ ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0:%.*]], 1073741823
469+ ; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i32 1, [[TMP1]]
470+ ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 373
471+ ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[TMP3]], 0
472+ ; CHECK-NEXT: ret i1 [[COND]]
473+ ;
474+
475+ entry:
476+ %isOK_ptr = getelementptr i32 , ptr @CG_MESSY , i32 %x
477+ %isOK = load i32 , ptr %isOK_ptr
478+ %cond = icmp slt i32 %isOK , 5
479+ ret i1 %cond
480+ }
481+
482+ define i1 @cmp_diff_load_constant_array_messy0 (i32 %x ){
483+ ; CHECK-LABEL: @cmp_diff_load_constant_array_messy0(
484+ ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1:%.*]], 1073741823
485+ ; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i32 1, [[TMP2]]
486+ ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 373
487+ ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[TMP4]], 0
488+ ; CHECK-NEXT: ret i1 [[COND]]
489+ ;
490+ %isOK_ptr = getelementptr i32 , ptr @CG_MESSY , i32 %x
491+ %isOK = load i16 , ptr %isOK_ptr
492+ %cond = icmp slt i16 %isOK , 5
493+ ret i1 %cond
494+ }
495+
496+ ; Load size larger than store size currently not supported.
497+ define i1 @cmp_diff_load_constant_array_messy1 (i32 %x ){
498+ ; CHECK-LABEL: @cmp_diff_load_constant_array_messy1(
499+ ; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr i6, ptr @CG_MESSY, i32 [[TMP1:%.*]]
500+ ; CHECK-NEXT: [[ISOK:%.*]] = load i16, ptr [[ISOK_PTR]], align 2
501+ ; CHECK-NEXT: [[COND:%.*]] = icmp slt i16 [[ISOK]], 5
502+ ; CHECK-NEXT: ret i1 [[COND]]
503+ ;
504+ %isOK_ptr = getelementptr i6 , ptr @CG_MESSY , i32 %x
505+ %isOK = load i16 , ptr %isOK_ptr
506+ %cond = icmp slt i16 %isOK , 5
507+ ret i1 %cond
508+ }
509+
510+ define i1 @cmp_load_constant_array_variable_icmp (i32 %x , i32 %y ) {
511+ ; CHECK-LABEL: @cmp_load_constant_array_variable_icmp(
512+ ; CHECK-NEXT: entry:
513+ ; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i32, ptr @CG_MESSY, i32 [[X:%.*]]
514+ ; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
515+ ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], [[Y:%.*]]
516+ ; CHECK-NEXT: ret i1 [[COND]]
517+ ;
518+ entry:
519+ %isOK_ptr = getelementptr inbounds i32 , ptr @CG_MESSY , i32 %x
520+ %isOK = load i32 , ptr %isOK_ptr
521+ %cond = icmp ult i32 %isOK , %y
522+ ret i1 %cond
523+ }
524+
525+ @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 ]
526+
527+ ; Offsets not supported if negative or larger than stride.
528+ define i1 @cmp_load_constant_additional_positive_offset (i32 %x ) {
529+ ; CHECK-LABEL: @cmp_load_constant_additional_positive_offset(
530+ ; CHECK-NEXT: entry:
531+ ; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 5, i32 [[X:%.*]]
532+ ; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
533+ ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
534+ ; CHECK-NEXT: ret i1 [[COND]]
535+ ;
536+ entry:
537+ %isOK_ptr = getelementptr inbounds [1 x i32 ], ptr @CG_CLEAR , i32 5 , i32 %x
538+ %isOK = load i32 , ptr %isOK_ptr
539+ %cond = icmp ult i32 %isOK , 5
540+ ret i1 %cond
541+ }
542+
543+ define i1 @cmp_load_constant_additional_negative_offset (i32 %x ) {
544+ ; CHECK-LABEL: @cmp_load_constant_additional_negative_offset(
545+ ; CHECK-NEXT: entry:
546+ ; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 [[X:%.*]], i32 -5
547+ ; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
548+ ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
549+ ; CHECK-NEXT: ret i1 [[COND]]
550+ ;
551+ entry:
552+ %isOK_ptr = getelementptr inbounds [1 x i32 ], ptr @CG_CLEAR , i32 %x , i32 -5
553+ %isOK = load i32 , ptr %isOK_ptr
554+ %cond = icmp ult i32 %isOK , 5
555+ ret i1 %cond
556+ }
0 commit comments