Merging r221318:

------------------------------------------------------------------------
r221318 | majnemer | 2014-11-04 15:49:08 -0800 (Tue, 04 Nov 2014) | 10 lines

Analysis: Make isSafeToSpeculativelyExecute fire less for divides

Divides and remainder operations do not behave like other operations
when they are given poison: they turn into undefined behavior.

It's really hard to know if the operands going into a div are or are not
poison.  Because of this, we should only choose to speculate if there
are constant operands which we can easily reason about.

This fixes PR21412.
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_35@223647 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer
2014-12-08 09:16:46 +00:00
parent 62e4903904
commit 7c5cb20b30
2 changed files with 27 additions and 21 deletions

View File

@@ -1987,23 +1987,31 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
default: default:
return true; return true;
case Instruction::UDiv: case Instruction::UDiv:
case Instruction::URem: case Instruction::URem: {
// x / y is undefined if y == 0, but calculations like x / 3 are safe. // x / y is undefined if y == 0.
return isKnownNonZero(Inst->getOperand(1), TD); const APInt *V;
if (match(Inst->getOperand(1), m_APInt(V)))
return *V != 0;
return false;
}
case Instruction::SDiv: case Instruction::SDiv:
case Instruction::SRem: { case Instruction::SRem: {
Value *Op = Inst->getOperand(1); // x / y is undefined if y == 0 or x == INT_MIN and y == -1
// x / y is undefined if y == 0 const APInt *X, *Y;
if (!isKnownNonZero(Op, TD)) if (match(Inst->getOperand(1), m_APInt(Y))) {
if (*Y != 0) {
if (*Y == -1) {
// The numerator can't be MinSignedValue if the denominator is -1.
if (match(Inst->getOperand(0), m_APInt(X)))
return !Y->isMinSignedValue();
// The numerator *might* be MinSignedValue.
return false; return false;
// x / y might be undefined if y == -1 }
unsigned BitWidth = getBitWidth(Op->getType(), TD); // The denominator is not 0 or -1, it's safe to proceed.
if (BitWidth == 0) return true;
}
}
return false; return false;
APInt KnownZero(BitWidth, 0);
APInt KnownOne(BitWidth, 0);
computeKnownBits(Op, KnownZero, KnownOne, TD);
return !!KnownZero;
} }
case Instruction::Load: { case Instruction::Load: {
const LoadInst *LI = cast<LoadInst>(Inst); const LoadInst *LI = cast<LoadInst>(Inst);

View File

@@ -3,12 +3,11 @@
; UDiv is safe to speculate if the denominator is known non-zero. ; UDiv is safe to speculate if the denominator is known non-zero.
; CHECK-LABEL: @safe_udiv( ; CHECK-LABEL: @safe_udiv(
; CHECK: %div = udiv i64 %x, %or ; CHECK: %div = udiv i64 %x, 2
; CHECK-NEXT: br label %for.body ; CHECK-NEXT: br label %for.body
define void @safe_udiv(i64 %x, i64 %m, i64 %n, i32* %p, i64* %q) nounwind { define void @safe_udiv(i64 %x, i64 %m, i64 %n, i32* %p, i64* %q) nounwind {
entry: entry:
%or = or i64 %m, 1
br label %for.body br label %for.body
for.body: ; preds = %entry, %for.inc for.body: ; preds = %entry, %for.inc
@@ -19,7 +18,7 @@ for.body: ; preds = %entry, %for.inc
br i1 %tobool, label %for.inc, label %if.then br i1 %tobool, label %for.inc, label %if.then
if.then: ; preds = %for.body if.then: ; preds = %for.body
%div = udiv i64 %x, %or %div = udiv i64 %x, 2
%arrayidx1 = getelementptr inbounds i64* %q, i64 %i.02 %arrayidx1 = getelementptr inbounds i64* %q, i64 %i.02
store i64 %div, i64* %arrayidx1, align 8 store i64 %div, i64* %arrayidx1, align 8
br label %for.inc br label %for.inc
@@ -69,13 +68,12 @@ for.end: ; preds = %for.inc, %entry
; known to have at least one zero bit. ; known to have at least one zero bit.
; CHECK-LABEL: @safe_sdiv( ; CHECK-LABEL: @safe_sdiv(
; CHECK: %div = sdiv i64 %x, %or ; CHECK: %div = sdiv i64 %x, 2
; CHECK-NEXT: br label %for.body ; CHECK-NEXT: br label %for.body
define void @safe_sdiv(i64 %x, i64 %m, i64 %n, i32* %p, i64* %q) nounwind { define void @safe_sdiv(i64 %x, i64 %m, i64 %n, i32* %p, i64* %q) nounwind {
entry: entry:
%and = and i64 %m, -3 %and = and i64 %m, -3
%or = or i64 %and, 1
br label %for.body br label %for.body
for.body: ; preds = %entry, %for.inc for.body: ; preds = %entry, %for.inc
@@ -86,7 +84,7 @@ for.body: ; preds = %entry, %for.inc
br i1 %tobool, label %for.inc, label %if.then br i1 %tobool, label %for.inc, label %if.then
if.then: ; preds = %for.body if.then: ; preds = %for.body
%div = sdiv i64 %x, %or %div = sdiv i64 %x, 2
%arrayidx1 = getelementptr inbounds i64* %q, i64 %i.02 %arrayidx1 = getelementptr inbounds i64* %q, i64 %i.02
store i64 %div, i64* %arrayidx1, align 8 store i64 %div, i64* %arrayidx1, align 8
br label %for.inc br label %for.inc