llvm.org GIT mirror llvm / 5489d32
[IPSCCP] Remove calls without side effects Summary: When performing constant propagation for call instructions we have historically replaced all uses of the return from a call, but not removed the call itself. This is required for correctness if the calls have side effects, however the compiler should be able to safely remove calls that don't have side effects. This allows the compiler to completely fold away calls to functions that have no side effects if the inputs are constant and the output can be determined at compile time. Reviewers: davide, sanjoy, bruno, dberlin Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D38856 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322125 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Bieneman 1 year, 8 months ago
5 changed file(s) with 49 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
534534 /// matters, isSafeToSpeculativelyExecute may be more appropriate.
535535 bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); }
536536
537 /// Return true if the instruction can be removed if the result is unused.
538 ///
539 /// When constant folding some instructions cannot be removed even if their
540 /// results are unused. Specifically terminator instructions and calls that
541 /// may have side effects cannot be removed without semantically changing the
542 /// generated program.
543 bool isSafeToRemove() const;
544
537545 /// Return true if the instruction is a variety of EH-block.
538546 bool isEHPad() const {
539547 switch (getOpcode()) {
588588 return isa(this);
589589 }
590590
591 bool Instruction::isSafeToRemove() const {
592 return (!isa(this) || !this->mayHaveSideEffects()) &&
593 !isa(this);
594 }
595
591596 bool Instruction::isAssociative() const {
592597 unsigned Opcode = getOpcode();
593598 if (isAssociative(Opcode))
18991899 if (Inst->getType()->isVoidTy())
19001900 continue;
19011901 if (tryToReplaceWithConstant(Solver, Inst)) {
1902 if (!isa(Inst) && !isa(Inst))
1902 if (Inst->isSafeToRemove())
19031903 Inst->eraseFromParent();
19041904 // Hey, we just changed something!
19051905 MadeChanges = true;
0 ; RUN: opt < %s -S -ipsccp | FileCheck %s
1 ; PR5596
2
3 ; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate
4 ; the result.
5
6 ; CHECK: define i32 @main() #0 {
7 ; CHECK-NEXT: entry:
8 ; CHECK-NOT: call
9 ; CHECK-NEXT: ret i32 123
10
11 define i32 @main() noreturn nounwind {
12 entry:
13 %call2 = tail call i32 @wwrite(i64 0) nounwind
14 ret i32 %call2
15 }
16
17 define internal i32 @wwrite(i64 %i) nounwind readnone {
18 entry:
19 switch i64 %i, label %sw.default [
20 i64 3, label %return
21 i64 10, label %return
22 ]
23
24 sw.default:
25 ret i32 123
26
27 return:
28 ret i32 0
29 }
30
31 ; CHECK: attributes #0 = { noreturn nounwind }
32 ; CHECK: attributes #1 = { nounwind readnone }
1414 ret i32 %call2
1515 }
1616
17 define internal i32 @wwrite(i64 %i) nounwind readnone {
17 define internal i32 @wwrite(i64 %i) nounwind {
1818 entry:
1919 switch i64 %i, label %sw.default [
2020 i64 3, label %return
2929 }
3030
3131 ; CHECK: attributes #0 = { noreturn nounwind }
32 ; CHECK: attributes #1 = { nounwind readnone }
33 ; CHECK: attributes [[NUW]] = { nounwind }
32 ; CHECK: attributes #1 = { nounwind }