From: Oliver Stannard Date: Fri, 24 Oct 2014 09:54:41 +0000 (+0000) Subject: [AArch64] Fix fast-isel of cbz of i1, i8, i16 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=9bb3f37aa44e39b937802cc9443c6a5aafa1de52 [AArch64] Fix fast-isel of cbz of i1, i8, i16 This fixes a miscompilation in the AArch64 fast-isel which was triggered when a branch is based on an icmp with condition eq or ne, and type i1, i8 or i16. The cbz instruction compares the whole 32-bit register, so values with the bottom 1, 8 or 16 bits clear would cause the wrong branch to be taken. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220553 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 5972d4aad78..a69185854f7 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -2181,6 +2181,12 @@ bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) { SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill, AArch64::sub_32); + if ((BW < 32) && !IsBitTest) { + EVT CmpEVT = TLI.getValueType(Ty, true); + SrcReg = + emitIntExt(CmpEVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ true); + } + // Emit the combined compare and branch instruction. SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs()); MachineInstrBuilder MIB = diff --git a/test/CodeGen/AArch64/fast-isel-cbz.ll b/test/CodeGen/AArch64/fast-isel-cbz.ll index 43263406160..4cd4b539401 100644 --- a/test/CodeGen/AArch64/fast-isel-cbz.ll +++ b/test/CodeGen/AArch64/fast-isel-cbz.ll @@ -1,8 +1,9 @@ ; RUN: llc -fast-isel -fast-isel-abort -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck %s -define i32 @icmp_eq_i1(i1 signext %a) { +define i32 @icmp_eq_i1(i1 %a) { ; CHECK-LABEL: icmp_eq_i1 -; CHECK: cbz w0, {{LBB.+_2}} +; CHECK: and [[REG:w[0-9]+]], w0, #0x1 +; CHECK: cbz [[REG]], {{LBB.+_2}} %1 = icmp eq i1 %a, 0 br i1 %1, label %bb1, label %bb2 bb2: @@ -11,9 +12,10 @@ bb1: ret i32 0 } -define i32 @icmp_eq_i8(i8 signext %a) { +define i32 @icmp_eq_i8(i8 %a) { ; CHECK-LABEL: icmp_eq_i8 -; CHECK: cbz w0, {{LBB.+_2}} +; CHECK: uxtb [[REG:w[0-9]+]], w0 +; CHECK: cbz [[REG]], {{LBB.+_2}} %1 = icmp eq i8 %a, 0 br i1 %1, label %bb1, label %bb2 bb2: @@ -22,9 +24,10 @@ bb1: ret i32 0 } -define i32 @icmp_eq_i16(i16 signext %a) { +define i32 @icmp_eq_i16(i16 %a) { ; CHECK-LABEL: icmp_eq_i16 -; CHECK: cbz w0, {{LBB.+_2}} +; CHECK: uxth [[REG:w[0-9]+]], w0 +; CHECK: cbz [[REG]], {{LBB.+_2}} %1 = icmp eq i16 %a, 0 br i1 %1, label %bb1, label %bb2 bb2: