[FastISel][AArch64] Don't fold the sign-/zero-extend from i1 into the compare.
authorJuergen Ributzka <juergen@apple.com>
Wed, 20 Aug 2014 16:34:15 +0000 (16:34 +0000)
committerJuergen Ributzka <juergen@apple.com>
Wed, 20 Aug 2014 16:34:15 +0000 (16:34 +0000)
This fixes a bug I introduced in a previous commit (r216033). Sign-/Zero-
extension from i1 cannot be folded into the ADDS/SUBS instructions. Instead both
operands have to be sign-/zero-extended with separate instructions.

Related to <rdar://problem/17913111>.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216073 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64FastISel.cpp
test/CodeGen/AArch64/arm64-fast-isel-icmp.ll

index 7320bb89dc47a2783d268f4e316d3f8f0baaa854..1bc5e424eac4c82b94d764c3c61716f0e0783eba 100644 (file)
@@ -773,19 +773,27 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
                                        const Value *LHS, const Value *RHS,
                                        bool IsZExt, bool WantResult) {
   AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
-  MVT SrcVT = RetVT;
+  bool NeedExtend = false;
   switch (RetVT.SimpleTy) {
-  default: return 0;
+  default:
+    return 0;
   case MVT::i1:
+    NeedExtend = true;
+    break;
   case MVT::i8:
-    ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB; RetVT = MVT::i32;
+    NeedExtend = true;
+    ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB;
     break;
   case MVT::i16:
-    ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH; RetVT = MVT::i32;
+    NeedExtend = true;
+    ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH;
+    break;
+  case MVT::i32:  // fall-through
+  case MVT::i64:
     break;
-  case MVT::i32: break;
-  case MVT::i64: break;
   }
+  MVT SrcVT = RetVT;
+  RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
 
   // Canonicalize immediates to the RHS first.
   if (UseAdds && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
@@ -805,7 +813,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
     return 0;
   bool LHSIsKill = hasTrivialKill(LHS);
 
-  if (ExtendType != AArch64_AM::InvalidShiftExtend)
+  if (NeedExtend)
     LHSReg = EmitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
 
   unsigned ResultReg = 0;
@@ -821,6 +829,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
   if (ResultReg)
     return ResultReg;
 
+  // Only extend the RHS within the instruction if there is a valid extend type.
   if (ExtendType != AArch64_AM::InvalidShiftExtend) {
     if (const auto *SI = dyn_cast<BinaryOperator>(RHS))
       if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1)))
@@ -867,6 +876,10 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
   if (!RHSReg)
     return 0;
   bool RHSIsKill = hasTrivialKill(RHS);
+
+  if (NeedExtend)
+    RHSReg = EmitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
+
   return emitAddsSubs_rr(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
                          WantResult);
 }
index bd1666bfb84a8961f2a7a6ae3ddae46d92865080..e0d7d413166428561a1f4a92cf7d8c269b732360 100644 (file)
@@ -172,6 +172,17 @@ entry:
   ret i32 %conv2
 }
 
+define i32 @icmp_i1_signed(i1 %a, i1 %b) nounwind {
+entry:
+; CHECK-LABEL: icmp_i1_signed
+; CHECK:       sbfx [[REG1:w[0-9]+]], w0, #0, #1
+; CHECK-NEXT:  sbfx [[REG2:w[0-9]+]], w1, #0, #1
+; CHECK-NEXT:  cmp  [[REG1]], [[REG2]]
+; CHECK-NEXT:  cset w0, gt
+  %cmp = icmp sgt i1 %a, %b
+  %conv2 = zext i1 %cmp to i32
+  ret i32 %conv2
+}
 
 define i32 @icmp_i16_signed_const(i16 %a) nounwind {
 entry: