1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[SCCP] Don't violate the lattice invariants

We marked values which are 'undef' as constant instead of undefined
which violates SCCP's invariants.  If we can figure out that a
computation results in 'undef', leave it in the undefined state.

This fixes PR16052.

llvm-svn: 257102
This commit is contained in:
David Majnemer 2016-01-07 21:36:16 +00:00
parent b8ea306e3f
commit 2296864d81
2 changed files with 68 additions and 15 deletions

View File

@ -757,9 +757,14 @@ void SCCPSolver::visitCastInst(CastInst &I) {
LatticeVal OpSt = getValueState(I.getOperand(0));
if (OpSt.isOverdefined()) // Inherit overdefinedness of operand
markOverdefined(&I);
else if (OpSt.isConstant()) // Propagate constant value
markConstant(&I, ConstantExpr::getCast(I.getOpcode(),
OpSt.getConstant(), I.getType()));
else if (OpSt.isConstant()) {
Constant *C =
ConstantExpr::getCast(I.getOpcode(), OpSt.getConstant(), I.getType());
if (isa<UndefValue>(C))
return;
// Propagate constant value
markConstant(&I, C);
}
}
@ -859,10 +864,14 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
LatticeVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
if (V1State.isConstant() && V2State.isConstant())
return markConstant(IV, &I,
ConstantExpr::get(I.getOpcode(), V1State.getConstant(),
V2State.getConstant()));
if (V1State.isConstant() && V2State.isConstant()) {
Constant *C = ConstantExpr::get(I.getOpcode(), V1State.getConstant(),
V2State.getConstant());
// X op Y -> undef.
if (isa<UndefValue>(C))
return;
return markConstant(IV, &I, C);
}
// If something is undef, wait for it to resolve.
if (!V1State.isOverdefined() && !V2State.isOverdefined())
@ -917,10 +926,13 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
LatticeVal &IV = ValueState[&I];
if (IV.isOverdefined()) return;
if (V1State.isConstant() && V2State.isConstant())
return markConstant(IV, &I, ConstantExpr::getCompare(I.getPredicate(),
V1State.getConstant(),
V2State.getConstant()));
if (V1State.isConstant() && V2State.isConstant()) {
Constant *C = ConstantExpr::getCompare(
I.getPredicate(), V1State.getConstant(), V2State.getConstant());
if (isa<UndefValue>(C))
return;
return markConstant(IV, &I, C);
}
// If operands are still undefined, wait for it to resolve.
if (!V1State.isOverdefined() && !V2State.isOverdefined())
@ -1020,8 +1032,11 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
Constant *Ptr = Operands[0];
auto Indices = makeArrayRef(Operands.begin() + 1, Operands.end());
markConstant(&I, ConstantExpr::getGetElementPtr(I.getSourceElementType(), Ptr,
Indices));
Constant *C =
ConstantExpr::getGetElementPtr(I.getSourceElementType(), Ptr, Indices);
if (isa<UndefValue>(C))
return;
markConstant(&I, C);
}
void SCCPSolver::visitStoreInst(StoreInst &SI) {
@ -1079,8 +1094,11 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
}
// Transform load from a constant into a constant if possible.
if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, DL))
if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, DL)) {
if (isa<UndefValue>(C))
return;
return markConstant(IV, &I, C);
}
// Otherwise we cannot say for certain what value this load will produce.
// Bail out.
@ -1122,8 +1140,12 @@ CallOverdefined:
// If we can constant fold this, mark the result of the call as a
// constant.
if (Constant *C = ConstantFoldCall(F, Operands, TLI))
if (Constant *C = ConstantFoldCall(F, Operands, TLI)) {
// call -> undef.
if (isa<UndefValue>(C))
return;
return markConstant(I, C);
}
}
// Otherwise, we don't know anything about this call, mark it overdefined.
@ -1379,6 +1401,11 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// X % undef -> undef. No change.
if (Op1LV.isUndefined()) break;
// X / 0 -> undef. No change.
// X % 0 -> undef. No change.
if (Op1LV.isConstant() && Op1LV.getConstant()->isZeroValue())
break;
// undef / X -> 0. X could be maxint.
// undef % X -> 0. X could be 1.
markForcedConstant(&I, Constant::getNullValue(ITy));

View File

@ -0,0 +1,26 @@
; RUN: opt < %s -S -ipsccp | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i64 @fn2() {
entry:
%conv = sext i32 undef to i64
%div = sdiv i64 8, %conv
%call2 = call i64 @fn1(i64 %div)
ret i64 %call2
}
; CHECK-DAG: define i64 @fn2(
; CHECK: %[[CALL:.*]] = call i64 @fn1(i64 undef)
define internal i64 @fn1(i64 %p1) {
entry:
%tobool = icmp ne i64 %p1, 0
%cond = select i1 %tobool, i64 %p1, i64 %p1
ret i64 %cond
}
; CHECK-DAG: define internal i64 @fn1(
; CHECK: %[[SEL:.*]] = select i1 undef, i64 undef, i64 undef
; CHECK: ret i64 %[[SEL]]