mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 06:24:57 +00:00
Teach instcombine to preserve the nsw bit by doing an after-the-fact analysis
when combining add and sub instructions. Patch by Pranav Bhandarkar! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137570 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -108,6 +108,44 @@ bool InstCombiner::ShouldChangeType(Type *From, Type *To) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true, if No Signed Wrap should be maintained for I.
|
||||||
|
// The No Signed Wrap flag can be kept if the operation "B (I.getOpcode) C",
|
||||||
|
// where both B and C should be ConstantInts, results in a constant that does
|
||||||
|
// not overflow. This function only handles the Add and Sub opcodes. For
|
||||||
|
// all other opcodes, the function conservatively returns false.
|
||||||
|
static bool MaintainNoSignedWrap(BinaryOperator &I, Value *B, Value *C) {
|
||||||
|
OverflowingBinaryOperator *OBO = dyn_cast<OverflowingBinaryOperator>(&I);
|
||||||
|
if (!OBO || !OBO->hasNoSignedWrap()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We reason about Add and Sub Only.
|
||||||
|
Instruction::BinaryOps Opcode = I.getOpcode();
|
||||||
|
if (Opcode != Instruction::Add &&
|
||||||
|
Opcode != Instruction::Sub) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantInt *CB = dyn_cast<ConstantInt>(B);
|
||||||
|
ConstantInt *CC = dyn_cast<ConstantInt>(C);
|
||||||
|
|
||||||
|
if (!CB || !CC) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const APInt &BVal = CB->getValue();
|
||||||
|
const APInt &CVal = CC->getValue();
|
||||||
|
bool Overflow = false;
|
||||||
|
|
||||||
|
if (Opcode == Instruction::Add) {
|
||||||
|
BVal.sadd_ov(CVal, Overflow);
|
||||||
|
} else {
|
||||||
|
BVal.ssub_ov(CVal, Overflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !Overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
|
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
|
||||||
/// operators which are associative or commutative:
|
/// operators which are associative or commutative:
|
||||||
@ -159,7 +197,13 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
|
|||||||
I.setOperand(1, V);
|
I.setOperand(1, V);
|
||||||
// Conservatively clear the optional flags, since they may not be
|
// Conservatively clear the optional flags, since they may not be
|
||||||
// preserved by the reassociation.
|
// preserved by the reassociation.
|
||||||
I.clearSubclassOptionalData();
|
if (MaintainNoSignedWrap(I, B, C)) {
|
||||||
|
I.clearSubclassOptionalData();
|
||||||
|
I.setHasNoSignedWrap(true);
|
||||||
|
} else {
|
||||||
|
I.clearSubclassOptionalData();
|
||||||
|
}
|
||||||
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
++NumReassoc;
|
++NumReassoc;
|
||||||
continue;
|
continue;
|
||||||
@ -241,14 +285,21 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
|
|||||||
Constant *C2 = cast<Constant>(Op1->getOperand(1));
|
Constant *C2 = cast<Constant>(Op1->getOperand(1));
|
||||||
|
|
||||||
Constant *Folded = ConstantExpr::get(Opcode, C1, C2);
|
Constant *Folded = ConstantExpr::get(Opcode, C1, C2);
|
||||||
Instruction *New = BinaryOperator::Create(Opcode, A, B);
|
BinaryOperator *New = BinaryOperator::Create(Opcode, A, B);
|
||||||
InsertNewInstWith(New, I);
|
InsertNewInstWith(New, I);
|
||||||
New->takeName(Op1);
|
New->takeName(Op1);
|
||||||
I.setOperand(0, New);
|
I.setOperand(0, New);
|
||||||
I.setOperand(1, Folded);
|
I.setOperand(1, Folded);
|
||||||
// Conservatively clear the optional flags, since they may not be
|
// Conservatively clear the optional flags, since they may not be
|
||||||
// preserved by the reassociation.
|
// preserved by the reassociation.
|
||||||
I.clearSubclassOptionalData();
|
if (MaintainNoSignedWrap(I, C1, C2)) {
|
||||||
|
I.clearSubclassOptionalData();
|
||||||
|
I.setHasNoSignedWrap(true);
|
||||||
|
New->setHasNoSignedWrap(true);
|
||||||
|
} else {
|
||||||
|
I.clearSubclassOptionalData();
|
||||||
|
}
|
||||||
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -37,3 +37,19 @@ define i64 @shl1(i64 %X, i64* %P) nounwind {
|
|||||||
%B = shl i64 %A, 8
|
%B = shl i64 %A, 8
|
||||||
ret i64 %B
|
ret i64 %B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: @preserve1
|
||||||
|
; CHECK: add nsw i32 %x, 5
|
||||||
|
define i32 @preserve1(i32 %x) nounwind {
|
||||||
|
%add = add nsw i32 %x, 2
|
||||||
|
%add3 = add nsw i32 %add, 3
|
||||||
|
ret i32 %add3
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: @nopreserve1
|
||||||
|
; CHECK: add i8 %x, -126
|
||||||
|
define i8 @nopreserve1(i8 %x) nounwind {
|
||||||
|
%add = add nsw i8 %x, 127
|
||||||
|
%add3 = add nsw i8 %add, 3
|
||||||
|
ret i8 %add3
|
||||||
|
}
|
Reference in New Issue
Block a user