Skip to content

Commit de49278

Browse files
committed
Teach instcombine to preserve the nsw bit by doing an after-the-fact analysis
when combining add and sub instructions. Patch by Pranav Bhandarkar! llvm-svn: 137570
1 parent c77574a commit de49278

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,44 @@ bool InstCombiner::ShouldChangeType(Type *From, Type *To) const {
108108
return true;
109109
}
110110

111+
// Return true, if No Signed Wrap should be maintained for I.
112+
// The No Signed Wrap flag can be kept if the operation "B (I.getOpcode) C",
113+
// where both B and C should be ConstantInts, results in a constant that does
114+
// not overflow. This function only handles the Add and Sub opcodes. For
115+
// all other opcodes, the function conservatively returns false.
116+
static bool MaintainNoSignedWrap(BinaryOperator &I, Value *B, Value *C) {
117+
OverflowingBinaryOperator *OBO = dyn_cast<OverflowingBinaryOperator>(&I);
118+
if (!OBO || !OBO->hasNoSignedWrap()) {
119+
return false;
120+
}
121+
122+
// We reason about Add and Sub Only.
123+
Instruction::BinaryOps Opcode = I.getOpcode();
124+
if (Opcode != Instruction::Add &&
125+
Opcode != Instruction::Sub) {
126+
return false;
127+
}
128+
129+
ConstantInt *CB = dyn_cast<ConstantInt>(B);
130+
ConstantInt *CC = dyn_cast<ConstantInt>(C);
131+
132+
if (!CB || !CC) {
133+
return false;
134+
}
135+
136+
const APInt &BVal = CB->getValue();
137+
const APInt &CVal = CC->getValue();
138+
bool Overflow = false;
139+
140+
if (Opcode == Instruction::Add) {
141+
BVal.sadd_ov(CVal, Overflow);
142+
} else {
143+
BVal.ssub_ov(CVal, Overflow);
144+
}
145+
146+
return !Overflow;
147+
}
148+
111149

112150
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
113151
/// operators which are associative or commutative:
@@ -159,7 +197,13 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
159197
I.setOperand(1, V);
160198
// Conservatively clear the optional flags, since they may not be
161199
// preserved by the reassociation.
162-
I.clearSubclassOptionalData();
200+
if (MaintainNoSignedWrap(I, B, C)) {
201+
I.clearSubclassOptionalData();
202+
I.setHasNoSignedWrap(true);
203+
} else {
204+
I.clearSubclassOptionalData();
205+
}
206+
163207
Changed = true;
164208
++NumReassoc;
165209
continue;
@@ -241,14 +285,21 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
241285
Constant *C2 = cast<Constant>(Op1->getOperand(1));
242286

243287
Constant *Folded = ConstantExpr::get(Opcode, C1, C2);
244-
Instruction *New = BinaryOperator::Create(Opcode, A, B);
288+
BinaryOperator *New = BinaryOperator::Create(Opcode, A, B);
245289
InsertNewInstWith(New, I);
246290
New->takeName(Op1);
247291
I.setOperand(0, New);
248292
I.setOperand(1, Folded);
249293
// Conservatively clear the optional flags, since they may not be
250294
// preserved by the reassociation.
251-
I.clearSubclassOptionalData();
295+
if (MaintainNoSignedWrap(I, C1, C2)) {
296+
I.clearSubclassOptionalData();
297+
I.setHasNoSignedWrap(true);
298+
New->setHasNoSignedWrap(true);
299+
} else {
300+
I.clearSubclassOptionalData();
301+
}
302+
252303
Changed = true;
253304
continue;
254305
}

llvm/test/Transforms/InstCombine/nsw.ll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,19 @@ define i64 @shl1(i64 %X, i64* %P) nounwind {
3737
%B = shl i64 %A, 8
3838
ret i64 %B
3939
}
40+
41+
; CHECK: @preserve1
42+
; CHECK: add nsw i32 %x, 5
43+
define i32 @preserve1(i32 %x) nounwind {
44+
%add = add nsw i32 %x, 2
45+
%add3 = add nsw i32 %add, 3
46+
ret i32 %add3
47+
}
48+
49+
; CHECK: @nopreserve1
50+
; CHECK: add i8 %x, -126
51+
define i8 @nopreserve1(i8 %x) nounwind {
52+
%add = add nsw i8 %x, 127
53+
%add3 = add nsw i8 %add, 3
54+
ret i8 %add3
55+
}

0 commit comments

Comments
 (0)