Skip to content

Commit

Permalink
[SimplifyCFG] Do not sink and merge inline-asm instructions.
Browse files Browse the repository at this point in the history
Conservatively disable sinking and merging inline-asm instructions as doing so
can potentially create arguments that cannot satisfy the inline-asm constraints.

For example, SimplifyCFG used to do the following transformation:

(before)
if.then:
  %0 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 8)
  br label %if.end
if.else:
  %1 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 6)
  br label %if.end

(after)
  %.sink = select i1 %tobool, i32 6, i32 8
  %0 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 %.sink)

This would result in a crash in the backend since only immediate integer operands
are permitted for constraint "n".

rdar://problem/30110806

Differential Revision: https://reviews.llvm.org/D29111

llvm-svn: 293025
  • Loading branch information
ahatanaka committed Jan 25, 2017
1 parent 732a531 commit 4ec7b20
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
8 changes: 8 additions & 0 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Expand Up @@ -1436,6 +1436,14 @@ static bool canSinkInstructions(
if (isa<PHINode>(I) || I->isEHPad() || isa<AllocaInst>(I) ||
I->getType()->isTokenTy())
return false;

// Conservatively return false if I is an inline-asm instruction. Sinking
// and merging inline-asm instructions can potentially create arguments
// that cannot satisfy the inline-asm constraints.
if (const auto *C = dyn_cast<CallInst>(I))
if (C->isInlineAsm())
return false;

// Everything must have only one use too, apart from stores which
// have no uses.
if (!isa<StoreInst>(I) && !I->hasOneUse())
Expand Down
24 changes: 24 additions & 0 deletions llvm/test/Transforms/SimplifyCFG/sink-common-code.ll
Expand Up @@ -768,6 +768,30 @@ if.end:
; CHECK-NOT: exact
; CHECK: }

; Check that simplifycfg doesn't sink and merge inline-asm instructions.

define i32 @test_inline_asm1(i32 %c, i32 %r6) {
entry:
%tobool = icmp eq i32 %c, 0
br i1 %tobool, label %if.else, label %if.then

if.then:
%0 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8)
br label %if.end

if.else:
%1 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6)
br label %if.end

if.end:
%r6.addr.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
ret i32 %r6.addr.0
}

; CHECK-LABEL: @test_inline_asm1(
; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8)
; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6)

declare i32 @call_target()

define void @test_operand_bundles(i1 %cond, i32* %ptr) {
Expand Down

0 comments on commit 4ec7b20

Please sign in to comment.