110 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S -data-layout="e-n16:32:64" | FileCheck %s3; RUN: opt < %s -passes=instcombine -S -data-layout="E-n16:32:64" | FileCheck %s4 5; Don't narrow if it would lose information about the dereferenceable range of the pointer.6 7define i32 @truncload_no_deref(ptr %ptr) {8; CHECK-LABEL: @truncload_no_deref(9; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[PTR:%.*]], align 410; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i3211; CHECK-NEXT: ret i32 [[R]]12;13 %x = load i64, ptr %ptr14 %r = trunc i64 %x to i3215 ret i32 %r16}17 18define i32 @truncload_small_deref(ptr dereferenceable(7) %ptr) {19; CHECK-LABEL: @truncload_small_deref(20; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[PTR:%.*]], align 421; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i3222; CHECK-NEXT: ret i32 [[R]]23;24 %x = load i64, ptr %ptr25 %r = trunc i64 %x to i3226 ret i32 %r27}28 29; On little-endian, we can narrow the load without an offset.30 31define i32 @truncload_deref(ptr dereferenceable(8) %ptr) {32; CHECK-LABEL: @truncload_deref(33; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[PTR:%.*]], align 434; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i3235; CHECK-NEXT: ret i32 [[R]]36;37 %x = load i64, ptr %ptr38 %r = trunc i64 %x to i3239 ret i32 %r40}41 42; Preserve alignment.43 44define i16 @truncload_align(ptr dereferenceable(14) %ptr) {45; CHECK-LABEL: @truncload_align(46; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[PTR:%.*]], align 1647; CHECK-NEXT: [[R:%.*]] = trunc i32 [[X]] to i1648; CHECK-NEXT: ret i16 [[R]]49;50 %x = load i32, ptr %ptr, align 1651 %r = trunc i32 %x to i1652 ret i16 %r53}54 55; Negative test - extra use means we would not eliminate the original load.56 57declare void @use(i64)58 59define i32 @truncload_extra_use(ptr dereferenceable(100) %ptr) {60; CHECK-LABEL: @truncload_extra_use(61; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[PTR:%.*]], align 262; CHECK-NEXT: call void @use(i64 [[X]])63; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i3264; CHECK-NEXT: ret i32 [[R]]65;66 %x = load i64, ptr %ptr, align 267 call void @use(i64 %x)68 %r = trunc i64 %x to i3269 ret i32 %r70}71 72; Negative test - don't create a load if the type is not allowed by the data-layout.73 74define i8 @truncload_type(ptr dereferenceable(9) %ptr) {75; CHECK-LABEL: @truncload_type(76; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[PTR:%.*]], align 277; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i878; CHECK-NEXT: ret i8 [[R]]79;80 %x = load i64, ptr %ptr, align 281 %r = trunc i64 %x to i882 ret i8 %r83}84 85; Negative test - don't transform volatiles.86 87define i32 @truncload_volatile(ptr dereferenceable(8) %ptr) {88; CHECK-LABEL: @truncload_volatile(89; CHECK-NEXT: [[X:%.*]] = load volatile i64, ptr [[PTR:%.*]], align 890; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i3291; CHECK-NEXT: ret i32 [[R]]92;93 %x = load volatile i64, ptr %ptr, align 894 %r = trunc i64 %x to i3295 ret i32 %r96}97 98; Preserve address space.99 100define i32 @truncload_address_space(ptr addrspace(1) dereferenceable(8) %ptr) {101; CHECK-LABEL: @truncload_address_space(102; CHECK-NEXT: [[X:%.*]] = load i64, ptr addrspace(1) [[PTR:%.*]], align 4103; CHECK-NEXT: [[R:%.*]] = trunc i64 [[X]] to i32104; CHECK-NEXT: ret i32 [[R]]105;106 %x = load i64, ptr addrspace(1) %ptr, align 4107 %r = trunc i64 %x to i32108 ret i32 %r109}110