From 997f5f10c6de8f0327225ff4e03582272094811a Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 22 May 2017 21:28:08 +0000 Subject: [PATCH] InstructionSimplify: don't speculate about Constants changing. When presented with an icmp/select pair, we can end up asking what would happen if we replaced one constant with another in an instruction. This is a mistake, while non-constant Values could become a constant, constants cannot change and trying to do so can lead to completely invalid IR (a GEP referencing a non-existant field in the original case). llvm-svn: 303580 --- llvm/lib/Analysis/InstructionSimplify.cpp | 4 +++ llvm/test/Transforms/EarlyCSE/const-speculation.ll | 39 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 llvm/test/Transforms/EarlyCSE/const-speculation.ll diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2e72d5a..69aa5b9 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3539,6 +3539,10 @@ static const Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, if (V == Op) return RepOp; + // We cannot replace a constant, and shouldn't even try. + if (isa(Op)) + return nullptr; + auto *I = dyn_cast(V); if (!I) return nullptr; diff --git a/llvm/test/Transforms/EarlyCSE/const-speculation.ll b/llvm/test/Transforms/EarlyCSE/const-speculation.ll new file mode 100644 index 0000000..5b7f2f5 --- /dev/null +++ b/llvm/test/Transforms/EarlyCSE/const-speculation.ll @@ -0,0 +1,39 @@ +; RUN: opt -early-cse -S %s | FileCheck %s + +%mystruct = type { i32 } + +; @var is global so that *every* GEP argument is Constant. +@var = external global %mystruct + +; Control flow is to make the dominance tree consider the final icmp before it +; gets to simplify the purely constant one (%tst). Since that icmp uses the +; select that gets considered next. Finally the select simplification looks at +; the %tst icmp and we don't want it to speculate about what happens if "i32 0" +; is actually "i32 1", broken universes are automatic UB. +; +; In this case doing the speculation would create an invalid GEP(@var, 0, 1) and +; crash. + +define i1 @test_constant_speculation() { +; CHECK-LABEL: define i1 @test_constant_speculation +entry: + br i1 undef, label %end, label %select + +select: +; CHECK: select: +; CHECK-NOT: icmp +; CHECK-NOT: getelementptr +; CHECK-NOT: select + + %tst = icmp eq i32 1, 0 + %elt = getelementptr %mystruct, %mystruct* @var, i64 0, i32 0 + %sel = select i1 %tst, i32* null, i32* %elt + br label %end + +end: +; CHECK: end: +; CHECK: %tmp = phi i32* [ null, %entry ], [ getelementptr inbounds (%mystruct, %mystruct* @var, i64 0, i32 0), %select ] + %tmp = phi i32* [null, %entry], [%sel, %select] + %res = icmp eq i32* %tmp, null + ret i1 %res +} -- 2.7.4