[FastISel][AArch64] Teach the address computation code to also fold sign-/zero-extends.
authorJuergen Ributzka <juergen@apple.com>
Tue, 7 Oct 2014 03:40:06 +0000 (03:40 +0000)
committerJuergen Ributzka <juergen@apple.com>
Tue, 7 Oct 2014 03:40:06 +0000 (03:40 +0000)
The code already folds sign-/zero-extends, but only if they are arguments to
mul and shift instructions. This extends the code to also fold them when they
are direct inputs.

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

lib/Target/AArch64/AArch64FastISel.cpp
test/CodeGen/AArch64/fast-isel-int-ext.ll

index 559a6bdf8ea804527c3419d4137cc2337f31c29e..110fd500e26f00d6444e62e7d7c52f5930b4a907 100644 (file)
@@ -776,6 +776,35 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
       }
     break;
   }
+  case Instruction::SExt:
+  case Instruction::ZExt: {
+    if (!Addr.getReg() || Addr.getOffsetReg())
+      break;
+
+    const Value *Src = nullptr;
+    // Fold the zext or sext when it won't become a noop.
+    if (const auto *ZE = dyn_cast<ZExtInst>(U)) {
+      if (!isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
+        Addr.setExtendType(AArch64_AM::UXTW);
+        Src = ZE->getOperand(0);
+      }
+    } else if (const auto *SE = dyn_cast<SExtInst>(U)) {
+      if (!isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
+        Addr.setExtendType(AArch64_AM::SXTW);
+        Src = SE->getOperand(0);
+      }
+    }
+
+    if (!Src)
+      break;
+
+    Addr.setShift(0);
+    unsigned Reg = getRegForValue(Src);
+    if (!Reg)
+      return false;
+    Addr.setOffsetReg(Reg);
+    return true;
+  }
   } // end switch
 
   if (Addr.getReg()) {
index 4a783a87a70a8dad2cf9a0709feaf21ae04653c0..866febac26222e2d777a1c8d66503061204ee0c9 100644 (file)
@@ -371,8 +371,7 @@ define i64 @load_register_sext_i32_to_i64(i64 %a, i64 %b) {
 ; Extend
 define i32 @load_extend_zext_i8_to_i32(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_zext_i8_to_i32
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrb w0, [x0, [[REG]]]
+; CHECK:       ldrb w0, [x0, w1, sxtw]
 ; CHECK-NOT:   uxtb
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -384,8 +383,7 @@ define i32 @load_extend_zext_i8_to_i32(i64 %a, i32 %b) {
 
 define i32 @load_extend_zext_i16_to_i32(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_zext_i16_to_i32
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrh w0, [x0, [[REG]]]
+; CHECK:       ldrh w0, [x0, w1, sxtw]
 ; CHECK-NOT:   uxth
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -397,8 +395,7 @@ define i32 @load_extend_zext_i16_to_i32(i64 %a, i32 %b) {
 
 define i64 @load_extend_zext_i8_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_zext_i8_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrb w0, [x0, [[REG]]]
+; CHECK:       ldrb w0, [x0, w1, sxtw]
 ; CHECK-NOT:   uxtb
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -410,8 +407,7 @@ define i64 @load_extend_zext_i8_to_i64(i64 %a, i32 %b) {
 
 define i64 @load_extend_zext_i16_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_zext_i16_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrh w0, [x0, [[REG]]]
+; CHECK:       ldrh w0, [x0, w1, sxtw]
 ; CHECK-NOT:   uxth
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -423,8 +419,7 @@ define i64 @load_extend_zext_i16_to_i64(i64 %a, i32 %b) {
 
 define i64 @load_extend_zext_i32_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_zext_i32_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldr w0, [x0, [[REG]]]
+; CHECK:       ldr w0, [x0, w1, sxtw]
 ; CHECK-NOT:   uxtw
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -436,8 +431,7 @@ define i64 @load_extend_zext_i32_to_i64(i64 %a, i32 %b) {
 
 define i32 @load_extend_sext_i8_to_i32(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_sext_i8_to_i32
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrsb w0, [x0, [[REG]]]
+; CHECK:       ldrsb w0, [x0, w1, sxtw]
 ; CHECK-NOT:   sxtb
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -449,8 +443,7 @@ define i32 @load_extend_sext_i8_to_i32(i64 %a, i32 %b) {
 
 define i32 @load_extend_sext_i16_to_i32(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_sext_i16_to_i32
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrsh w0, [x0, [[REG]]]
+; CHECK:       ldrsh w0, [x0, w1, sxtw]
 ; CHECK-NOT:   sxth
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -462,8 +455,7 @@ define i32 @load_extend_sext_i16_to_i32(i64 %a, i32 %b) {
 
 define i64 @load_extend_sext_i8_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_sext_i8_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrsb x0, [x0, [[REG]]]
+; CHECK:       ldrsb x0, [x0, w1, sxtw]
 ; CHECK-NOT:   sxtb
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -475,8 +467,7 @@ define i64 @load_extend_sext_i8_to_i64(i64 %a, i32 %b) {
 
 define i64 @load_extend_sext_i16_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_sext_i16_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrsh x0, [x0, [[REG]]]
+; CHECK:       ldrsh x0, [x0, w1, sxtw]
 ; CHECK-NOT:   sxth
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1
@@ -488,8 +479,7 @@ define i64 @load_extend_sext_i16_to_i64(i64 %a, i32 %b) {
 
 define i64 @load_extend_sext_i32_to_i64(i64 %a, i32 %b) {
 ; CHECK-LABEL: load_extend_sext_i32_to_i64
-; CHECK:       sxtw [[REG:x[0-9]+]], w1
-; CHECK-NEXT:  ldrsw x0, [x0, [[REG]]]
+; CHECK:       ldrsw x0, [x0, w1, sxtw]
 ; CHECK-NOT:   sxtw
   %1 = sext i32 %b to i64
   %2 = add i64 %a, %1