diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -331,6 +331,8 @@ case Intrinsic::ceil: Opcode = ISD::FCEIL; break; case Intrinsic::trunc: Opcode = ISD::FTRUNC; break; case Intrinsic::rint: Opcode = ISD::FRINT; break; + case Intrinsic::lrint: Opcode = ISD::LRINT; break; + case Intrinsic::llrint: Opcode = ISD::LLRINT; break; case Intrinsic::nearbyint: Opcode = ISD::FNEARBYINT; break; case Intrinsic::round: Opcode = ISD::FROUND; break; case Intrinsic::minnum: Opcode = ISD::FMINNUM; break; diff --git a/llvm/test/CodeGen/PowerPC/llrint-ctr-crash.ll b/llvm/test/CodeGen/PowerPC/llrint-ctr-crash.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/llrint-ctr-crash.ll @@ -0,0 +1,171 @@ +; RUN: llc -verify-machineinstrs -O1 < %s | FileCheck %s + +; These tests ensure that LLVM will not incorrectly optimize a loop when using +; lrint and llrint intrinsics. The test cases are largely adapted from +; ctrloop-*.ll test cases. + +; CHECK: lrint_f32_ctr_crash +; CHECK: bl lrintf +; CHECK-NOT: bdnz +; a < b +define void @lrint_f32_ctr_crash(i32* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i32, i32* %p, i32 %i.04 + %0 = load i32, i32* %arrayidx, align 1 + %lrint = tail call i32 @llvm.lrint.f32(float 42.0) + store i32 %lrint, i32* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: lrint_f64_ctr_crash +; CHECK: bl lrint +; CHECK-NOT: bdnz +; a < b +define void @lrint_f64_ctr_crash(i32* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i32, i32* %p, i32 %i.04 + %0 = load i32, i32* %arrayidx, align 1 + %lrint = tail call i32 @llvm.lrint.f64(double 42.0) + store i32 %lrint, i32* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: lrint_f128_ctr_crash +; CHECK: bl lrintl +; CHECK-NOT: bdnz +; a < b +define void @lrint_f128_ctr_crash(i32* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i32, i32* %p, i32 %i.04 + %0 = load i32, i32* %arrayidx, align 1 + %n = sitofp i8 42 to fp128 + %lrint = tail call i32 @llvm.lrint.f128(fp128 %n) + store i32 %lrint, i32* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: llrint_f32_ctr_crash +; CHECK: bl llrintf +; CHECK-NOT: bdnz +; a < b +define void @llrint_f32_ctr_crash(i64* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i64, i64* %p, i32 %i.04 + %0 = load i64, i64* %arrayidx, align 1 + %llrint = tail call i64 @llvm.llrint.f32(float 42.0) + store i64 %llrint, i64* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: llrint_f64_ctr_crash +; CHECK: bl llrint +; CHECK-NOT: bdnz +; a < b +define void @llrint_f64_ctr_crash(i64* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i64, i64* %p, i32 %i.04 + %0 = load i64, i64* %arrayidx, align 1 + %llrint = tail call i64 @llvm.llrint.f64(double 42.0) + store i64 %llrint, i64* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: llrint_f128_ctr_crash +; CHECK: bl llrintl +; CHECK-NOT: bdnz +; a < b +define void @llrint_f128_ctr_crash(i64* nocapture %p, i32 %a, i32 %b) nounwind { +entry: + %cmp3 = icmp slt i32 42, %b + br i1 %cmp3, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.04 = phi i32 [ 42, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds i64, i64* %p, i32 %i.04 + %0 = load i64, i64* %arrayidx, align 1 + %n = sitofp i8 42 to fp128 + %llrint = tail call i64 @llvm.llrint.f128(fp128 %n) + store i64 %llrint, i64* %arrayidx, align 1 + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %inc, %b + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +declare i32 @llvm.lrint.f32(float) nounwind readnone +declare i32 @llvm.lrint.f64(double) nounwind readnone +declare i32 @llvm.lrint.f128(fp128) nounwind readnone +declare i64 @llvm.llrint.f32(float) nounwind readnone +declare i64 @llvm.llrint.f64(double) nounwind readnone +declare i64 @llvm.llrint.f128(fp128) nounwind readnone +