diff --git a/llvm/lib/CodeGen/TailDuplicator.cpp b/llvm/lib/CodeGen/TailDuplicator.cpp --- a/llvm/lib/CodeGen/TailDuplicator.cpp +++ b/llvm/lib/CodeGen/TailDuplicator.cpp @@ -623,6 +623,14 @@ if (InstrCount > MaxDuplicateCount) return false; + + // Because INLINEASM_BR cannot be predicated, leave it in its own block. If + // Converter still appears to produce optimal code without having to special + // case INLINEASM_BR. + // FIXME: improve If Conversion to avoid attempting to predicate such + // instructions, and fix improper tail merging of these instructions. + if (MI.getOpcode() == TargetOpcode::INLINEASM_BR) + return false; } // Check if any of the successors of TailBB has a PHI node in which the diff --git a/llvm/test/CodeGen/ARM/ifcvt-inline-asm.ll b/llvm/test/CodeGen/ARM/ifcvt-inline-asm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/ifcvt-inline-asm.ll @@ -0,0 +1,55 @@ +; RUN: llc -mtriple=arm-linux-gnueabi -print-machineinstrs=tailduplication %s \ +; RUN: -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK-TAILDUP %s + +; RUN: llc -mtriple=arm-linux-gnueabi -print-machineinstrs=if-converter %s \ +; RUN: -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK-IFCVT %s + +; Check that INLINEASM_BR did not get duplicated into the previously duplicated +; blocks by Tail Duplication. + +; CHECK-TAILDUP: bb.2.if.else: +; CHECK-TAILDUP: INLINEASM &"str $1, $0" [sideeffect] [mayload] [attdialect], $0:[mem:Q], killed renamable $r0, $1:[reguse:GPR], killed renamable $r1 +; CHECK-TAILDUP: bb.3.if.end: +; CHECK-TAILDUP: INLINEASM_BR &"" [sideeffect] [attdialect], $0:[imm], blockaddress(@f, %ir-block.g) + +; Check that INLINEASM_BR was merged back into one block successfully by If Convert. +; CHECK-IFCVT: bb.0.entry: +; CHECK-IFCVT: INLINEASM &"str $1, $0" [sideeffect] [mayload] [attdialect], $0:[mem:Q], killed renamable $r0, $1:[reguse:GPR], killed renamable $r1 +; CHECK-IFCVT: INLINEASM_BR &"" [sideeffect] [attdialect], $0:[imm], blockaddress(@f, %ir-block.g) +; CHECK-IFCVT: bb.1.asm.fallthrough: +; CHECK-IFCVT: bb.2.g (address-taken): + +; Test case is a c-reduced then bugpointed sound/soc/ti/davinci-i2s.c from the +; Linux kernel. + +@a = external dso_local local_unnamed_addr global i32*, align 4 +@c = external dso_local local_unnamed_addr global i32, align 4 + +define dso_local i32 @f() #0 { +entry: + %0 = load i32, i32* @c, align 4 + %tobool = icmp eq i32 %0, 0 + %1 = load i32*, i32** @a, align 4 + br i1 %tobool, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void asm sideeffect "str $1, $0", "*Qo,r"(i32* %1, i32 1) #1 + br label %if.end + +if.else: ; preds = %entry + tail call void asm sideeffect "str $1, $0", "*Qo,r"(i32* %1, i32 0) #1 + br label %if.end + +if.end: ; preds = %if.else, %if.then + callbr void asm sideeffect "", "X"(i8* blockaddress(@f, %g)) #1 + to label %asm.fallthrough [label %g] + +asm.fallthrough: ; preds = %if.end + unreachable + +g: ; preds = %if.end + ret i32 undef +} + +attributes #0 = { "use-soft-float"="false" } +attributes #1 = { nounwind }