1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00
llvm-mirror/test/Transforms/SimplifyCFG/switch_msan.ll
Vitaly Buka 9fd3523265 [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

llvm-svn: 371138
2019-09-05 22:49:34 +00:00

103 lines
3.5 KiB
LLVM

; 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
}