diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 06b900fcb85a4..56d0fc9e85bd1 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -6917,7 +6917,7 @@ bool VPCostContext::skipCostComputation(Instruction *UI, bool IsVector) const { SkipCostComputation.contains(UI); } -unsigned VPCostContext::getPredBlockCostDivisor(BasicBlock *BB) const { +uint64_t VPCostContext::getPredBlockCostDivisor(BasicBlock *BB) const { return CM.getPredBlockCostDivisor(CostKind, BB); } diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h index 113ca8c4d0f7c..0d4a842c700f6 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h +++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h @@ -366,7 +366,7 @@ struct VPCostContext { /// \returns how much the cost of a predicated block should be divided by. /// Forwards to LoopVectorizationCostModel::getPredBlockCostDivisor. - unsigned getPredBlockCostDivisor(BasicBlock *BB) const; + uint64_t getPredBlockCostDivisor(BasicBlock *BB) const; /// Returns the OperandInfo for \p V, if it is a live-in. TargetTransformInfo::OperandValueInfo getOperandInfo(VPValue *V) const; diff --git a/llvm/test/Transforms/LoopVectorize/X86/cost-divisor-overflow.ll b/llvm/test/Transforms/LoopVectorize/X86/cost-divisor-overflow.ll new file mode 100644 index 0000000000000..565966bc06c7e --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/X86/cost-divisor-overflow.ll @@ -0,0 +1,67 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6 +; RUN: opt < %s -passes=loop-vectorize -S | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-grtev4-linux-gnu" + +; Tests that the computed predicate block cost divisor doesn't get coerced to +; zero and cause a division by zero error. +; See https://github.com/llvm/llvm-project/issues/187584 +define void @foo(ptr %x, i1 %y, i1 %z) { +; CHECK-LABEL: define void @foo( +; CHECK-SAME: ptr [[X:%.*]], i1 [[Y:%.*]], i1 [[Z:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] +; CHECK: [[EXIT:.*]]: +; CHECK-NEXT: ret void +; CHECK: [[LOOP_HEADER]]: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ADD:%.*]], %[[LOOP_LATCH:.*]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[PHI3:%.*]] = phi i64 [ [[PHI7:%.*]], %[[LOOP_LATCH]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[PHI4:%.*]] = phi i1 [ [[YNOT:%.*]], %[[LOOP_LATCH]] ], [ [[Y]], %[[ENTRY]] ] +; CHECK-NEXT: [[PHI5:%.*]] = phi i1 [ [[ZNOT:%.*]], %[[LOOP_LATCH]] ], [ [[Z]], %[[ENTRY]] ] +; CHECK-NEXT: br i1 [[Y]], label %[[BB4:.*]], label %[[LOOP_LATCH]] +; CHECK: [[BB4]]: +; CHECK-NEXT: br i1 [[Z]], label %[[LOOP_LATCH]], label %[[BB5:.*]], !prof [[PROF0:![0-9]+]] +; CHECK: [[BB5]]: +; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[X]], align 8 +; CHECK-NEXT: [[CALL:%.*]] = call i64 @llvm.smin.i64(i64 [[LOAD]], i64 [[PHI3]]) +; CHECK-NEXT: br label %[[LOOP_LATCH]] +; CHECK: [[LOOP_LATCH]]: +; CHECK-NEXT: [[PHI7]] = phi i64 [ [[PHI3]], %[[BB4]] ], [ [[CALL]], %[[BB5]] ], [ [[PHI3]], %[[LOOP_HEADER]] ] +; CHECK-NEXT: [[ADD]] = add i64 [[PHI]], 1 +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[PHI]], 1 +; CHECK-NEXT: [[YNOT]] = xor i1 [[PHI4]], true +; CHECK-NEXT: [[ZNOT]] = xor i1 [[PHI5]], true +; CHECK-NEXT: br i1 [[ICMP]], label %[[EXIT]], label %[[LOOP_HEADER]] +; +entry: + br label %loop.header + +exit: ; preds = %loop.latch + ret void + +loop.header: ; preds = %loop.latch, %entry + %phi = phi i64 [ %add, %loop.latch ], [ 0, %entry ] + %phi3 = phi i64 [ %phi7, %loop.latch ], [ 0, %entry ] + %phi4 = phi i1 [ %ynot, %loop.latch ], [ %y, %entry ] + %phi5 = phi i1 [ %znot, %loop.latch ], [ %z, %entry ] + br i1 %y, label %bb4, label %loop.latch + +bb4: ; preds = %loop.header + br i1 %z, label %loop.latch, label %bb5, !prof !0 + +bb5: ; preds = %bb4 + %load = load i64, ptr %x, align 8 + %call = call i64 @llvm.smin.i64(i64 %load, i64 %phi3) + br label %loop.latch + +loop.latch: ; preds = %bb5, %bb4, %loop.header + %phi7 = phi i64 [ %phi3, %bb4 ], [ %call, %bb5 ], [ %phi3, %loop.header ] + %add = add i64 %phi, 1 + %icmp = icmp eq i64 %phi, 1 + %ynot = xor i1 %phi4, true; + %znot = xor i1 %phi5, true; + br i1 %icmp, label %exit, label %loop.header +} + +!0 = !{!"branch_weights", i32 -2147483648, i32 0}