1 ; RUN: llc -verify-machineinstrs -ppc-reduce-cr-logicals \ 2 ; RUN: -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s 3 4 ; Test case is reduced from the snappy benchmark. 5 ; Verify MachineLICM will always hoist trivially rematerializable instructions even when register pressure is high. 6 7 %"class.snappy::SnappyDecompressor" = type <{ %"class.snappy::Source"*, i8*, i8*, i32, i8, [5 x i8], [6 x i8] }> 8 %"class.snappy::Source" = type { i32 (...)** } 9 %"struct.snappy::iovec" = type { i8*, i64 } 10 %"class.snappy::SnappyIOVecWriter" = type { %"struct.snappy::iovec"*, i64, i64, i64, i64, i64 } 11 12 @_ZN6snappy8internalL10char_tableE = internal unnamed_addr constant [5 x i16] [i16 1, i16 2052, i16 4097, i16 8193, i16 2], align 2 13 @_ZN6snappy8internalL8wordmaskE = internal unnamed_addr constant [5 x i32] [i32 0, i32 255, i32 65535, i32 16777215, i32 -1], align 4 14 15 ; Function Attrs: argmemonly nounwind 16 declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) #2 17 ; Function Attrs: argmemonly nounwind 18 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #2 19 20 define linkonce_odr void @ZN6snappyDecompressor_(%"class.snappy::SnappyDecompressor"* %this, %"class.snappy::SnappyIOVecWriter"* %writer) { 21 ; CHECK-LABEL: ZN6snappyDecompressor_: 22 ; CHECK: # %bb.0: # %entry 23 ; CHECK: addis 3, 2, _ZN6snappy8internalL8wordmaskE@toc@ha 24 ; CHECK-DAG: addi 25, 3, _ZN6snappy8internalL8wordmaskE@toc@l 25 ; CHECK-DAG: addis 5, 2, _ZN6snappy8internalL10char_tableE@toc@ha 26 ; CHECK-DAG: addi 24, 5, _ZN6snappy8internalL10char_tableE@toc@l 27 ; CHECK: b .LBB0_2 28 ; CHECK: .LBB0_2: # %for.cond 29 ; CHECK-NOT: addis {{[0-9]+}}, 2, _ZN6snappy8internalL8wordmaskE@toc@ha 30 ; CHECK-NOT: addis {{[0-9]+}}, 2, _ZN6snappy8internalL10char_tableE@toc@ha 31 ; CHECK: bctrl 32 entry: 33 %ip_limit_ = getelementptr inbounds %"class.snappy::SnappyDecompressor", %"class.snappy::SnappyDecompressor"* %this, i64 0, i32 2 34 %0 = bitcast i8** %ip_limit_ to i64* 35 %curr_iov_index_.i = getelementptr inbounds %"class.snappy::SnappyIOVecWriter", %"class.snappy::SnappyIOVecWriter"* %writer, i64 0, i32 2 36 %curr_iov_written_.i = getelementptr inbounds %"class.snappy::SnappyIOVecWriter", %"class.snappy::SnappyIOVecWriter"* %writer, i64 0, i32 3 37 %1 = bitcast i64* %curr_iov_written_.i to <2 x i64>* 38 br label %for.cond 39 40 for.cond: ; preds = %if.end82, %if.then56, %if.end49, %entry 41 %ip.0 = phi i8* [ null, %entry ], [ %add.ptr50, %if.end49 ], [ null, %if.then56 ], [ undef, %if.end82 ] 42 %incdec.ptr = getelementptr inbounds i8, i8* %ip.0, i64 1 43 %2 = load i8, i8* %ip.0, align 1 44 %conv = zext i8 %2 to i32 45 br i1 undef, label %if.then7, label %if.else 46 47 if.then7: ; preds = %for.cond 48 %3 = lshr i32 %conv, 2 49 %add = add nuw nsw i32 %3, 1 50 %conv9 = zext i32 %add to i64 51 %4 = load i64, i64* %0, align 8 52 %sub.ptr.sub13 = sub i64 %4, 0 53 %5 = load i64, i64* undef, align 8 54 %6 = load i64, i64* null, align 8 55 %sub.i = sub i64 %5, %6 56 %cmp.i = icmp ult i32 %add, 17 57 %cmp2.i = icmp ugt i64 %sub.ptr.sub13, 20 58 %or.cond.i = and i1 %cmp.i, %cmp2.i 59 %cmp4.i = icmp ugt i64 %sub.i, 15 60 %or.cond13.i = and i1 %or.cond.i, %cmp4.i 61 br i1 %or.cond13.i, label %land.lhs.true5.i, label %if.end17 62 63 land.lhs.true5.i: ; preds = %if.then7 64 %7 = load %"struct.snappy::iovec"*, %"struct.snappy::iovec"** undef, align 8 65 %8 = load i64, i64* %curr_iov_index_.i, align 8 66 %9 = load i64, i64* %curr_iov_written_.i, align 8 67 %sub6.i = sub i64 0, %9 68 %cmp7.i = icmp ugt i64 %sub6.i, 15 69 br i1 %cmp7.i, label %cleanup102, label %if.end17 70 71 if.end17: ; preds = %land.lhs.true5.i, %if.then7 72 %sub = add nsw i64 %conv9, -60 73 %10 = load i32, i32* undef, align 4 74 %arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* @_ZN6snappy8internalL8wordmaskE, i64 0, i64 %sub 75 %11 = load i32, i32* %arrayidx, align 4 76 %and21 = and i32 %11, %10 77 %add22 = add i32 %and21, 1 78 %conv23 = zext i32 %add22 to i64 79 %add.ptr24 = getelementptr inbounds i8, i8* %incdec.ptr, i64 %sub 80 br label %if.end25 81 82 if.end25: ; preds = %if.end17 83 %sub.ptr.rhs.cast28 = ptrtoint i8* %add.ptr24 to i64 84 %cmp30233 = icmp ugt i64 %conv23, 0 85 br i1 %cmp30233, label %while.body.preheader, label %while.end 86 87 while.body.preheader: ; preds = %if.end25 88 %add.i158256 = add i64 %6, 0 89 %cmp.i160257 = icmp ugt i64 %add.i158256, %5 90 br i1 %cmp.i160257, label %cleanup105, label %while.cond.preheader.i 91 92 while.cond.preheader.i: ; preds = %while.body.preheader 93 %call39 = call i8* undef(%"class.snappy::Source"* undef, i64* nonnull undef) 94 unreachable 95 96 while.end: ; preds = %if.end25 97 br label %while.cond.preheader.i176 98 99 while.cond.preheader.i176: ; preds = %while.end 100 br i1 undef, label %if.end49, label %while.body.lr.ph.i182 101 102 while.body.lr.ph.i182: ; preds = %while.cond.preheader.i176 103 %.pre.i181 = load i64, i64* %curr_iov_written_.i, align 8 104 %12 = load %"struct.snappy::iovec"*, %"struct.snappy::iovec"** undef, align 8 105 %13 = load i64, i64* %curr_iov_index_.i, align 8 106 %iov_len.i185 = getelementptr inbounds %"struct.snappy::iovec", %"struct.snappy::iovec"* %12, i64 %13, i32 1 107 %14 = load i64, i64* %iov_len.i185, align 8 108 br label %cond.end.i190 109 110 cond.end.i190: ; preds = %while.body.lr.ph.i182 111 br i1 undef, label %if.end18.i207, label %if.then10.i193 112 113 if.then10.i193: ; preds = %cond.end.i190 114 %add12.i191 = add i64 %13, 1 115 %iov_len22.phi.trans.insert.i194 = getelementptr inbounds %"struct.snappy::iovec", %"struct.snappy::iovec"* %12, i64 %add12.i191, i32 1 116 %.pre48.i195 = load i64, i64* %iov_len22.phi.trans.insert.i194, align 8 117 br label %if.end18.i207 118 119 if.end18.i207: ; preds = %if.then10.i193, %cond.end.i190 120 %15 = phi i64 [ %.pre.i181, %cond.end.i190 ], [ 0, %if.then10.i193 ] 121 %16 = phi i64 [ %14, %cond.end.i190 ], [ %.pre48.i195, %if.then10.i193 ] 122 %17 = phi i64 [ %13, %cond.end.i190 ], [ %add12.i191, %if.then10.i193 ] 123 %sub.i197 = sub i64 %16, %15 124 %cmp.i.i198 = icmp ult i64 %sub.i197, %conv23 125 %.sroa.speculated.i199 = select i1 %cmp.i.i198, i64 %sub.i197, i64 %conv23 126 %iov_base.i.i200 = getelementptr inbounds %"struct.snappy::iovec", %"struct.snappy::iovec"* %12, i64 %17, i32 0 127 %18 = load i8*, i8** %iov_base.i.i200, align 8 128 %add.ptr.i.i201 = getelementptr inbounds i8, i8* %18, i64 %15 129 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %add.ptr.i.i201, i8* %add.ptr24, i64 %.sroa.speculated.i199, i1 false) #12 130 %add30.i203 = add i64 0, %.sroa.speculated.i199 131 store i64 %add30.i203, i64* null, align 8 132 %.pre245 = load i64, i64* %0, align 8 133 br label %if.end49 134 135 if.end49: ; preds = %if.end18.i207, %while.cond.preheader.i176 136 %19 = phi i64 [ %.pre245, %if.end18.i207 ], [ %4, %while.cond.preheader.i176 ] 137 %add.ptr50 = getelementptr inbounds i8, i8* %add.ptr24, i64 %conv23 138 %sub.ptr.sub54 = sub i64 %19, 0 139 %cmp55 = icmp slt i64 %sub.ptr.sub54, 5 140 br i1 %cmp55, label %if.then56, label %for.cond 141 142 if.then56: ; preds = %if.end49 143 br label %for.cond 144 145 if.else: ; preds = %for.cond 146 %idxprom = zext i8 %2 to i64 147 %arrayidx68 = getelementptr inbounds [5 x i16], [5 x i16]* @_ZN6snappy8internalL10char_tableE, i64 0, i64 %idxprom 148 %20 = load i16, i16* %arrayidx68, align 2 149 %conv69 = zext i16 %20 to i64 150 %21 = load i32, i32* undef, align 4 151 %shr71 = lshr i64 %conv69, 11 152 %arrayidx72 = getelementptr inbounds [5 x i32], [5 x i32]* @_ZN6snappy8internalL8wordmaskE, i64 0, i64 %shr71 153 %22 = load i32, i32* %arrayidx72, align 4 154 %and73 = and i32 %22, %21 155 %conv74 = zext i32 %and73 to i64 156 %add79 = add nuw nsw i64 0, %conv74 157 %call80 = call zeroext i1 @_ZN6snappy17SnappyIOVecWriterAppendFromSelfEmm(%"class.snappy::SnappyIOVecWriter"* %writer, i64 %add79, i64 undef) 158 br i1 %call80, label %if.end82, label %cleanup105 159 160 if.end82: ; preds = %if.else 161 br label %for.cond 162 163 cleanup102: ; preds = %land.lhs.true5.i 164 %iov_base.i.i = getelementptr inbounds %"struct.snappy::iovec", %"struct.snappy::iovec"* %7, i64 %8, i32 0 165 %23 = load i8*, i8** %iov_base.i.i, align 8 166 %add.ptr.i.i = getelementptr inbounds i8, i8* %23, i64 %9 167 call void @llvm.memmove.p0i8.p0i8.i64(i8* %add.ptr.i.i, i8* %incdec.ptr, i64 16, i1 false) #12 168 %24 = load <2 x i64>, <2 x i64>* %1, align 8 169 %25 = insertelement <2 x i64> undef, i64 %conv9, i32 0 170 %26 = shufflevector <2 x i64> %25, <2 x i64> undef, <2 x i32> zeroinitializer 171 %27 = add <2 x i64> %24, %26 172 store <2 x i64> %27, <2 x i64>* undef, align 8 173 unreachable 174 175 cleanup105: ; preds = %if.else, %while.body.preheader 176 ret void 177 } 178 179 ; Function Attrs: inlinehint 180 declare zeroext i1 @_ZN6snappy17SnappyIOVecWriterAppendFromSelfEmm(%"class.snappy::SnappyIOVecWriter"*, i64, i64) local_unnamed_addr #10 align 2 181