[ARM] icmp %x, -C can be lowered to a simple ADDS or CMN
authorJames Molloy <james.molloy@arm.com>
Fri, 9 Sep 2016 13:35:28 +0000 (13:35 +0000)
committerJames Molloy <james.molloy@arm.com>
Fri, 9 Sep 2016 13:35:28 +0000 (13:35 +0000)
Tell TargetTransformInfo about this so ConstantHoisting is informed.

llvm-svn: 281043

llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
llvm/test/CodeGen/ARM/immcost.ll

index 4881933..13d57c0 100644 (file)
@@ -73,6 +73,17 @@ int ARMTTIImpl::getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
       // Conversion to BIC is free, and means we can use ~Imm instead.
       return std::min(getIntImmCost(Imm, Ty), getIntImmCost(~Imm, Ty));
 
+  if (Opcode == Instruction::ICmp && Imm.isNegative() &&
+      Ty->getIntegerBitWidth() == 32) {
+    int64_t NegImm = -Imm.getSExtValue();
+    if (ST->isThumb2() && NegImm < 1<<12)
+      // icmp X, #-C -> cmn X, #C
+      return 0;
+    if (ST->isThumb() && NegImm < 1<<8)
+      // icmp X, #-C -> adds X, #C
+      return 0;
+  }
+
   return getIntImmCost(Imm, Ty);
 }
 
index bfc1fdd..43a4989 100644 (file)
@@ -37,3 +37,37 @@ ret:
   ret void
 }
 
+; CHECK: Function: test_icmp_neg
+; CHECK-NOT: Collect constant
+define void @test_icmp_neg(i1 %cond, i32 %arg, i32 %arg2) {
+entry:
+  %a = icmp ne i32 %arg, -5
+  call void @g2(i1 %a)
+  br i1 %cond, label %true, label %ret
+
+true:
+  %b = icmp ne i32 %arg2, -5
+  call void @g2(i1 %b)
+  br label %ret
+
+ret:
+  ret void
+}
+declare void @g2(i1)
+
+; CHECK: Function: test_icmp_neg2
+; CHECK: Hoist constant (i32 -500) to BB entry
+define void @test_icmp_neg2(i1 %cond, i32 %arg, i32 %arg2) {
+entry:
+  %a = icmp ne i32 %arg, -500
+  call void @g2(i1 %a)
+  br i1 %cond, label %true, label %ret
+
+true:
+  %b = icmp ne i32 %arg2, -500
+  call void @g2(i1 %b)
+  br label %ret
+
+ret:
+  ret void
+}