Use sext in fast isel.
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 6 Apr 2015 22:29:07 +0000 (22:29 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 6 Apr 2015 22:29:07 +0000 (22:29 +0000)
Fast isel used to zero extends immediates to 64 bits. This normally goes
unnoticed because the value is truncated to 32 bits for output.

Two cases were it is noticed:

* We fail to use smaller encodings.
* If the original constant was smaller than i32.

In the tests using i1 constants, codegen would change to use -1, which is fine
(and matches what regular isel does) since only the lowest bit is then used.

Instead, this patch then changes the ir to use i8 constants, which looks more
like what clang produces.

llvm-svn: 234249

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
llvm/test/CodeGen/Mips/Fast-ISel/logopm.ll
llvm/test/CodeGen/X86/fast-isel-i1.ll
llvm/test/CodeGen/X86/fast-isel-sext.ll [new file with mode: 0644]

index 8f504e1..cf26425 100644 (file)
@@ -425,7 +425,7 @@ bool FastISel::selectBinaryOp(const User *I, unsigned ISDOpcode) {
 
   // Check if the second operand is a constant and handle it appropriately.
   if (const auto *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
-    uint64_t Imm = CI->getZExtValue();
+    uint64_t Imm = CI->getSExtValue();
 
     // Transform "sdiv exact X, 8" -> "sra X, 3".
     if (ISDOpcode == ISD::SDIV && isa<BinaryOperator>(I) &&
index cfb751f..0f0c3bf 100644 (file)
@@ -68,11 +68,12 @@ entry:
 
 ; Function Attrs: noinline nounwind
 define void @andUb1() #0 {
+; clang uses i8 constants for booleans, so we test with an i8 1.
 entry:
-  %0 = load i8, i8* @ub1, align 1, !tbaa !2
-  %conv = trunc i8 %0 to i1
-  %and = and i1 %conv, 1
-  %conv1 = zext i1 %and to i8
+  %x = load i8, i8* @ub1, align 1, !tbaa !2
+  %and = and i8 %x, 1
+  %conv = trunc i8 %and to i1
+  %conv1 = zext i1 %conv to i8
   store i8 %conv1, i8* @ub, align 1, !tbaa !2
 ; CHECK-LABEL:  .ent    andUb1
 ; CHECK:        lui     $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
@@ -138,10 +139,10 @@ entry:
 ; Function Attrs: noinline nounwind
 define void @orUb1() #0 {
 entry:
-  %0 = load i8, i8* @ub1, align 1, !tbaa !2
-  %conv = trunc i8 %0 to i1
-  %or = or i1 %conv, 1
-  %conv1 = zext i1 %or to i8
+  %x = load i8, i8* @ub1, align 1, !tbaa !2
+  %or = or i8 %x, 1
+  %conv = trunc i8 %or to i1
+  %conv1 = zext i1 %conv to i8
   store i8 %conv1, i8* @ub, align 1, !tbaa !2
 ; CHECK-LABEL:  .ent    orUb1
 ; CHECK:        lui     $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
@@ -208,10 +209,10 @@ entry:
 ; Function Attrs: noinline nounwind
 define void @xorUb1() #0 {
 entry:
-  %0 = load i8, i8* @ub1, align 1, !tbaa !2
-  %conv = trunc i8 %0 to i1
-  %xor = xor i1 %conv, 1
-  %conv1 = zext i1 %xor to i8
+  %x = load i8, i8* @ub1, align 1, !tbaa !2
+  %xor = xor i8 1, %x
+  %conv = trunc i8 %xor to i1
+  %conv1 = zext i1 %conv to i8
   store i8 %conv1, i8* @ub, align 1, !tbaa !2
 ; CHECK-LABEL:  .ent    xorUb1
 ; CHECK:        lui     $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
index d72a31c..589de76 100644 (file)
@@ -23,14 +23,15 @@ exit:               ; preds = %next
 
 define void @test2(i8* %a) nounwind {
 entry:
+; clang uses i8 constants for booleans, so we test with an i8 1.
 ; CHECK-LABEL: test2:
 ; CHECK: movb {{.*}} %al
 ; CHECK-NEXT: xorb $1, %al
 ; CHECK-NEXT: testb $1
   %tmp = load i8, i8* %a, align 1
-  %tobool = trunc i8 %tmp to i1
-  %tobool2 = xor i1 %tobool, true
-  br i1 %tobool2, label %if.then, label %if.end
+  %xor = xor i8 %tmp, 1
+  %tobool = trunc i8 %xor to i1
+  br i1 %tobool, label %if.then, label %if.end
 
 if.then:
   call void @test2(i8* null)
diff --git a/llvm/test/CodeGen/X86/fast-isel-sext.ll b/llvm/test/CodeGen/X86/fast-isel-sext.ll
new file mode 100644 (file)
index 0000000..ca1558e
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llc -mtriple=x86_64-linux -fast-isel -show-mc-encoding < %s | FileCheck %s
+
+; CHECK-LABEL: f:
+; CHECK:       addl $-2, %eax         # encoding: [0x83,0xc0,0xfe]
+define i32 @f(i32* %y) {
+  %x = load i32, i32* %y
+  %dec = add i32 %x, -2
+  ret i32 %dec
+}