261 lines · plain
1; RUN: llc < %s -mtriple=arm-eabi -mcpu=generic | FileCheck %s2; RUN: llc < %s -mtriple=thumbv6m-eabi | FileCheck %s -check-prefix=CHECK-V6M-THUMB3 4define i32 @sadd(i32 %a, i32 %b) local_unnamed_addr #0 {5; CHECK-LABEL: sadd:6; CHECK: adds r0, r0, r17; CHECK-NEXT: movvc pc, lr8entry:9 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)10 %1 = extractvalue { i32, i1 } %0, 111 br i1 %1, label %trap, label %cont12 13trap:14 tail call void @llvm.trap() #215 unreachable16 17cont:18 %2 = extractvalue { i32, i1 } %0, 019 ret i32 %220 21}22 23define i32 @uadd(i32 %a, i32 %b) local_unnamed_addr #0 {24; CHECK-LABEL: uadd:25; CHECK: adds r0, r0, r126; CHECK-NEXT: movlo pc, lr27entry:28 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)29 %1 = extractvalue { i32, i1 } %0, 130 br i1 %1, label %trap, label %cont31 32trap:33 tail call void @llvm.trap() #234 unreachable35 36cont:37 %2 = extractvalue { i32, i1 } %0, 038 ret i32 %239 40}41 42define i32 @ssub(i32 %a, i32 %b) local_unnamed_addr #0 {43; CHECK-LABEL: ssub:44; CHECK: subs r0, r0, r145; CHECK-NEXT: movvc pc, lr46entry:47 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)48 %1 = extractvalue { i32, i1 } %0, 149 br i1 %1, label %trap, label %cont50 51trap:52 tail call void @llvm.trap() #253 unreachable54 55cont:56 %2 = extractvalue { i32, i1 } %0, 057 ret i32 %258 59}60 61define i32 @usub(i32 %a, i32 %b) local_unnamed_addr #0 {62; CHECK-LABEL: usub:63; CHECK: subs r0, r0, r164; CHECK-NEXT: movhs pc, lr65entry:66 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32 %b)67 %1 = extractvalue { i32, i1 } %0, 168 br i1 %1, label %trap, label %cont69 70trap:71 tail call void @llvm.trap() #272 unreachable73 74cont:75 %2 = extractvalue { i32, i1 } %0, 076 ret i32 %277 78}79 80define i32 @smul(i32 %a, i32 %b) local_unnamed_addr #0 {81; CHECK-LABEL: smul:82; CHECK: smull r0, r[[RHI:[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}83; CHECK-NEXT: cmp r[[RHI]], r0, asr #3184; CHECK-NEXT: moveq pc, lr85; CHECK-V6M-THUMB-LABEL: smul:86; CHECK-V6M-THUMB: bl __aeabi_lmul87entry:88 %0 = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %a, i32 %b)89 %1 = extractvalue { i32, i1 } %0, 190 br i1 %1, label %trap, label %cont91 92trap:93 tail call void @llvm.trap() #294 unreachable95 96cont:97 %2 = extractvalue { i32, i1 } %0, 098 ret i32 %299}100 101define i32 @umul(i32 %a, i32 %b) local_unnamed_addr #0 {102; CHECK-LABEL: umul:103; CHECK: umull r0, r[[RHI:[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}104; CHECK-NEXT: cmp r[[RHI]], #0105; CHECK-NEXT: moveq pc, lr106; CHECK-V6M-THUMB-LABEL: umul:107; CHECK-V6M-THUMB: bl __aeabi_lmul108entry:109 %0 = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %a, i32 %b)110 %1 = extractvalue { i32, i1 } %0, 1111 br i1 %1, label %trap, label %cont112 113trap:114 tail call void @llvm.trap() #2115 unreachable116 117cont:118 %2 = extractvalue { i32, i1 } %0, 0119 ret i32 %2120}121 122define void @sum(ptr %a, ptr %b, i32 %n) local_unnamed_addr #0 {123; CHECK-LABEL: sum:124; CHECK: ldr [[R0:r[0-9]+]],125; CHECK-NEXT: ldr [[R1:r[0-9]+|lr]],126; CHECK-NEXT: adds [[R2:r[0-9]+]], [[R1]], [[R0]]127; CHECK-NEXT: strvc [[R2]],128; CHECK-NEXT: addsvc129; CHECK-NEXT: bvs130entry:131 %cmp7 = icmp eq i32 %n, 0132 br i1 %cmp7, label %for.cond.cleanup, label %for.body133 134for.cond.cleanup:135 ret void136 137for.body:138 %i.08 = phi i32 [ %7, %cont2 ], [ 0, %entry ]139 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.08140 %0 = load i32, ptr %arrayidx, align 4141 %arrayidx1 = getelementptr inbounds i32, ptr %a, i32 %i.08142 %1 = load i32, ptr %arrayidx1, align 4143 %2 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %1, i32 %0)144 %3 = extractvalue { i32, i1 } %2, 1145 br i1 %3, label %trap, label %cont146 147trap:148 tail call void @llvm.trap() #2149 unreachable150 151cont:152 %4 = extractvalue { i32, i1 } %2, 0153 store i32 %4, ptr %arrayidx1, align 4154 %5 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.08, i32 1)155 %6 = extractvalue { i32, i1 } %5, 1156 br i1 %6, label %trap, label %cont2157 158cont2:159 %7 = extractvalue { i32, i1 } %5, 0160 %cmp = icmp eq i32 %7, %n161 br i1 %cmp, label %for.cond.cleanup, label %for.body162 163}164 165define void @extern_loop(i32 %n) local_unnamed_addr #0 {166; Do not replace the compare around the clobbering call.167; CHECK: bl external_fn168; CHECK-NEXT: adds169; CHECK-NEXT: bvs170entry:171 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %n, i32 1)172 %1 = extractvalue { i32, i1 } %0, 1173 br i1 %1, label %trap, label %cont.lr.ph174 175cont.lr.ph:176 %2 = extractvalue { i32, i1 } %0, 0177 %cmp5 = icmp sgt i32 %2, 0178 br i1 %cmp5, label %for.body.preheader, label %for.cond.cleanup179 180for.body.preheader:181 br label %for.body182 183trap:184 tail call void @llvm.trap() #2185 unreachable186 187for.cond.cleanup:188 ret void189 190for.body:191 %i.046 = phi i32 [ %5, %cont1 ], [ 0, %for.body.preheader ]192 tail call void @external_fn() #4193 %3 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.046, i32 1)194 %4 = extractvalue { i32, i1 } %3, 1195 br i1 %4, label %trap, label %cont1196 197cont1:198 %5 = extractvalue { i32, i1 } %3, 0199 %cmp = icmp slt i32 %5, %2200 br i1 %cmp, label %for.body, label %for.cond.cleanup201}202 203declare void @external_fn(...) local_unnamed_addr #0204 205define i32 @are_equal(ptr nocapture readonly %a1, ptr nocapture readonly %a2, i32 %n) local_unnamed_addr #0 {206; CHECK-LABEL: are_equal207; CHECK: subs r{{[0-9]+}}, r{{[0-9]+}}, #1208; CHECK-NEXT: bne209entry:210 %tobool7 = icmp eq i32 %n, 0211 br i1 %tobool7, label %while.end, label %land.rhs.preheader212 213land.rhs.preheader:214 br label %land.rhs215 216while.cond:217 %tobool = icmp eq i32 %dec9, 0218 br i1 %tobool, label %while.end, label %land.rhs219 220land.rhs:221 %dec9.in = phi i32 [ %dec9, %while.cond ], [ %n, %land.rhs.preheader ]222 %dec9 = add nsw i32 %dec9.in, -1223 %arrayidx = getelementptr inbounds i32, ptr %a1, i32 %dec9224 %0 = load i32, ptr %arrayidx, align 4225 %arrayidx1 = getelementptr inbounds i32, ptr %a2, i32 %dec9226 %1 = load i32, ptr %arrayidx1, align 4227 %cmp = icmp eq i32 %0, %1228 br i1 %cmp, label %while.cond, label %while.end229 230while.end:231 %n.addr.0.lcssa = phi i32 [ 0, %entry ], [ 0, %while.cond ], [ %dec9.in, %land.rhs ]232 %cmp2 = icmp slt i32 %n.addr.0.lcssa, 1233 %conv = zext i1 %cmp2 to i32234 ret i32 %conv235}236 237define i1 @no__mulodi4(i32 %a, i64 %b, ptr %c) {238; CHECK-LABEL: no__mulodi4239; CHECK-NOT: bl __mulodi4240entry:241 %0 = sext i32 %a to i64242 %1 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 %b)243 %2 = extractvalue { i64, i1 } %1, 1244 %3 = extractvalue { i64, i1 } %1, 0245 %4 = trunc i64 %3 to i32246 %5 = sext i32 %4 to i64247 %6 = icmp ne i64 %3, %5248 %7 = or i1 %2, %6249 store i32 %4, ptr %c, align 4250 ret i1 %7251}252 253declare void @llvm.trap() #2254declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1255declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) #1256declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) #1257declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) #1258declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) #1259declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) #1260declare { i64, i1 } @llvm.smul.with.overflow.i64(i64, i64)261