[llvm] r371138 - [SimplifyCFG] Don't SimplifyBranchOnICmpChain with ExtraCase
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 5 15:49:34 PDT 2019
Author: vitalybuka
Date: Thu Sep 5 15:49:34 2019
New Revision: 371138
URL: http://llvm.org/viewvc/llvm-project?rev=371138&view=rev
Log:
[SimplifyCFG] Don't SimplifyBranchOnICmpChain with ExtraCase
Summary:
Here we try to avoid issues with "explicit branch" with SimplifyBranchOnICmpChain
which can check on undef. Msan by design reports branches on uninitialized
memory and undefs, so we have false report here.
In general msan does not like when we convert
```
// If at least one of them is true we can MSAN is ok if another is undefs
if (a || b)
return;
```
into
```
// If 'a' is undef MSAN will complain even if 'b' is true
if (a)
return;
if (b)
return;
```
Example
Before optimization we had something like this:
```
while (true) {
bool maybe_undef = doStuff();
while (true) {
char c = getChar();
if (c != 10 && c != 13)
continue
break;
}
// we know that c == 10 || c == 13 if we get here,
// so msan know that branch is not affected by maybe_undef
if (maybe_undef || c == 10 || c == 13)
continue;
return;
}
```
SimplifyBranchOnICmpChain will convert that into
```
while (true) {
bool maybe_undef = doStuff();
while (true) {
char c = getChar();
if (c != 10 && c != 13)
continue;
break;
}
// however msan will complain here:
if (maybe_undef)
continue;
// we know that c == 10 || c == 13, so either way we will get continue
switch(c) {
case 10: continue;
case 13: continue;
}
return;
}
```
Reviewers: eugenis, efriedma
Reviewed By: eugenis, efriedma
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67205
Added:
llvm/trunk/test/Transforms/SimplifyCFG/switch_msan.ll
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=371138&r1=371137&r2=371138&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Thu Sep 5 15:49:34 2019
@@ -3729,12 +3729,17 @@ static bool SimplifyBranchOnICmpChain(Br
BasicBlock *BB = BI->getParent();
+ // MSAN does not like undefs as branch condition which can be introduced
+ // with "explicit branch".
+ if (ExtraCase && BB->getParent()->hasFnAttribute(Attribute::SanitizeMemory))
+ return false;
+
LLVM_DEBUG(dbgs() << "Converting 'icmp' chain with " << Values.size()
<< " cases into SWITCH. BB is:\n"
<< *BB);
// If there are any extra values that couldn't be folded into the switch
- // then we evaluate them with an explicit branch first. Split the block
+ // then we evaluate them with an explicit branch first. Split the block
// right before the condbr to handle it.
if (ExtraCase) {
BasicBlock *NewBB =
Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_msan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_msan.ll?rev=371138&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_msan.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_msan.ll Thu Sep 5 15:49:34 2019
@@ -0,0 +1,102 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+declare i8 @next_char();
+
+define void @test_no_msan() {
+; CHECK-LABEL: @test_no_msan(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: br label [[WHILE_BODY_I:%.*]]
+; CHECK: while.body.i:
+; CHECK-NEXT: [[MAYBE_UNDEF:%.*]] = phi i1 [ undef, [[WHILE_BODY]] ], [ [[NEXT_MAYBE_UNDEF:%.*]], [[WHILE_BODY_I]] ]
+; CHECK-NEXT: [[C:%.*]] = call fastcc signext i8 @next_char()
+; CHECK-NEXT: [[C_10:%.*]] = icmp eq i8 [[C]], 10
+; CHECK-NEXT: [[C_13:%.*]] = icmp eq i8 [[C]], 13
+; CHECK-NEXT: [[C_10_OR_13:%.*]] = or i1 [[C_10]], [[C_13]]
+; CHECK-NEXT: [[NEXT_MAYBE_UNDEF]] = or i1 [[MAYBE_UNDEF]], [[C_10_OR_13]]
+; CHECK-NEXT: [[C_NOT_10_OR_13:%.*]] = xor i1 [[C_10_OR_13]], true
+; CHECK-NEXT: br i1 [[C_NOT_10_OR_13]], label [[WHILE_BODY_I]], label [[WHILE_BODY_I_BREAK:%.*]]
+; CHECK: while.body.i.break:
+; CHECK-NEXT: br i1 [[MAYBE_UNDEF]], label [[WHILE_BODY]], label [[SWITCH_EARLY_TEST:%.*]]
+; CHECK: switch.early.test:
+; CHECK-NEXT: switch i8 [[C]], label [[RETURN:%.*]] [
+; CHECK-NEXT: i8 13, label [[WHILE_BODY]]
+; CHECK-NEXT: i8 10, label [[WHILE_BODY]]
+; CHECK-NEXT: ]
+; CHECK: return:
+; CHECK-NEXT: ret void
+;
+
+entry:
+ br label %while.body
+
+while.body:
+ br label %while.body.i
+
+while.body.i:
+ %maybe_undef = phi i1 [ undef, %while.body ], [ %next_maybe_undef, %while.body.i ]
+ %c = call fastcc signext i8 @next_char()
+ %c_10 = icmp eq i8 %c, 10
+ %c_13 = icmp eq i8 %c, 13
+ %c_10_or_13 = or i1 %c_10, %c_13
+ %next_maybe_undef = or i1 %maybe_undef, %c_10_or_13
+ %c_not_10_or_13 = xor i1 %c_10_or_13, true
+ br i1 %c_not_10_or_13, label %while.body.i, label %while.body.i.break
+
+while.body.i.break:
+ ; NEXT_MAYBE_UNDEF is never undef if here
+ br i1 %next_maybe_undef, label %while.body, label %return
+
+
+return:
+ ret void
+}
+
+
+define void @test_msan() sanitize_memory {
+; CHECK-LABEL: @test_msan(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: br label [[WHILE_BODY_I:%.*]]
+; CHECK: while.body.i:
+; CHECK-NEXT: [[MAYBE_UNDEF:%.*]] = phi i1 [ undef, [[WHILE_BODY]] ], [ [[NEXT_MAYBE_UNDEF:%.*]], [[WHILE_BODY_I]] ]
+; CHECK-NEXT: [[C:%.*]] = call fastcc signext i8 @next_char()
+; CHECK-NEXT: [[C_10:%.*]] = icmp eq i8 [[C]], 10
+; CHECK-NEXT: [[C_13:%.*]] = icmp eq i8 [[C]], 13
+; CHECK-NEXT: [[C_10_OR_13:%.*]] = or i1 [[C_10]], [[C_13]]
+; CHECK-NEXT: [[NEXT_MAYBE_UNDEF]] = or i1 [[MAYBE_UNDEF]], [[C_10_OR_13]]
+; CHECK-NEXT: [[C_NOT_10_OR_13:%.*]] = xor i1 [[C_10_OR_13]], true
+; CHECK-NEXT: br i1 [[C_NOT_10_OR_13]], label [[WHILE_BODY_I]], label [[WHILE_BODY_I_BREAK:%.*]]
+; CHECK: while.body.i.break:
+; CHECK-NEXT: br i1 [[NEXT_MAYBE_UNDEF]], label [[WHILE_BODY]], label [[RETURN:%.*]]
+; CHECK: return:
+; CHECK-NEXT: ret void
+;
+
+entry:
+ br label %while.body
+
+while.body:
+ br label %while.body.i
+
+while.body.i:
+ %maybe_undef = phi i1 [ undef, %while.body ], [ %next_maybe_undef, %while.body.i ]
+ %c = call fastcc signext i8 @next_char()
+ %c_10 = icmp eq i8 %c, 10
+ %c_13 = icmp eq i8 %c, 13
+ %c_10_or_13 = or i1 %c_10, %c_13
+ %next_maybe_undef = or i1 %maybe_undef, %c_10_or_13
+ %c_not_10_or_13 = xor i1 %c_10_or_13, true
+ br i1 %c_not_10_or_13, label %while.body.i, label %while.body.i.break
+
+while.body.i.break:
+ ; NEXT_MAYBE_UNDEF is never undef if here
+ br i1 %next_maybe_undef, label %while.body, label %return
+
+
+return:
+ ret void
+}
More information about the llvm-commits
mailing list