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:
parent
b8ea306e3f
commit
2296864d81
@ -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));
|
||||
|
26
test/Transforms/IPConstantProp/PR16052.ll
Normal file
26
test/Transforms/IPConstantProp/PR16052.ll
Normal 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]]
|
Loading…
Reference in New Issue
Block a user