From d258eb3ec5cc5c9a28d3a8cd80241c9df24ce3a1 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 24 Oct 2012 19:53:01 +0000 Subject: [PATCH] Fix a miscompilation caused by a typo. When turning a adde with negative value into a sbc with a positive number, the immediate should be complemented, not negated. Also added a missing pattern for ARM codegen. rdar://12559385 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166613 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 12 ++++++------ lib/Target/ARM/ARMInstrThumb2.td | 2 +- test/CodeGen/ARM/carry.ll | 13 +++++++++++++ test/CodeGen/Thumb2/carry.ll | 13 +++++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index a78ada0a809..b193a5c033f 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -283,15 +283,13 @@ class RegConstraint { // ARM specific transformation functions and pattern fragments. // -// imm_neg_XFORM - Return a imm value packed into the format described for -// imm_neg defs below. +// imm_neg_XFORM - Return the negation of an i32 immediate value. def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); }]>; -// so_imm_not_XFORM - Return a so_imm value packed into the format described for -// so_imm_not def below. -def so_imm_not_XFORM : SDNodeXFormgetTargetConstant(~(int)N->getZExtValue(), MVT::i32); }]>; @@ -314,7 +312,7 @@ def so_imm_neg : Operand, PatLeaf<(imm), [{ def so_imm_not_asmoperand : AsmOperandClass { let Name = "ARMSOImmNot"; } def so_imm_not : Operand, PatLeaf<(imm), [{ return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1; - }], so_imm_not_XFORM> { + }], imm_not_XFORM> { let ParserMatchClass = so_imm_not_asmoperand; } @@ -3120,6 +3118,8 @@ def : ARMPat<(ARMaddc GPR:$src, imm0_65535_neg:$imm), // for part of the negation. def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR), (SBCri GPR:$src, so_imm_not:$imm)>; +def : ARMPat<(ARMadde GPR:$src, imm0_65535_neg:$imm, CPSR), + (SBCrr GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>; // Note: These are implemented in C++ code, because they have to generate // ADD/SUBrs instructions, which use a complex pattern that a xform function diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 2c62fdb3866..1684339d6f5 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1953,7 +1953,7 @@ def : T2Pat<(ARMadde rGPR:$src, imm0_255_not:$imm, CPSR), def : T2Pat<(ARMadde rGPR:$src, t2_so_imm_not:$imm, CPSR), (t2SBCri rGPR:$src, t2_so_imm_not:$imm)>; def : T2Pat<(ARMadde rGPR:$src, imm0_65535_neg:$imm, CPSR), - (t2SBCrr rGPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>; + (t2SBCrr rGPR:$src, (t2MOVi16 (imm_not_XFORM imm:$imm)))>; // Select Bytes -- for disassembly only diff --git a/test/CodeGen/ARM/carry.ll b/test/CodeGen/ARM/carry.ll index f84774d9b61..bf51cd627b3 100644 --- a/test/CodeGen/ARM/carry.ll +++ b/test/CodeGen/ARM/carry.ll @@ -45,3 +45,16 @@ entry: %0 = sub nsw i64 0, %x ret i64 %0 } + +; rdar://12559385 +define i64 @f5(i32 %vi) { +entry: +; CHECK: f5: +; CHECK: movw [[REG:r[0-9]+]], #36102 +; CHECK: sbc r{{[0-9]+}}, r{{[0-9]+}}, [[REG]] + %v0 = zext i32 %vi to i64 + %v1 = xor i64 %v0, -155057456198619 + %v4 = add i64 %v1, 155057456198619 + %v5 = add i64 %v4, %v1 + ret i64 %v5 +} diff --git a/test/CodeGen/Thumb2/carry.ll b/test/CodeGen/Thumb2/carry.ll index de6f6e260de..85b4370fa59 100644 --- a/test/CodeGen/Thumb2/carry.ll +++ b/test/CodeGen/Thumb2/carry.ll @@ -20,3 +20,16 @@ entry: %tmp2 = sub i64 %tmp1, %b ret i64 %tmp2 } + +; rdar://12559385 +define i64 @f3(i32 %vi) { +entry: +; CHECK: f3: +; CHECK: movw [[REG:r[0-9]+]], #36102 +; CHECK: sbcs r{{[0-9]+}}, [[REG]] + %v0 = zext i32 %vi to i64 + %v1 = xor i64 %v0, -155057456198619 + %v4 = add i64 %v1, 155057456198619 + %v5 = add i64 %v4, %v1 + ret i64 %v5 +}