]> granicus.if.org Git - llvm/commitdiff
Merging r327540:
authorTom Stellard <tstellar@redhat.com>
Tue, 8 May 2018 22:21:28 +0000 (22:21 +0000)
committerTom Stellard <tstellar@redhat.com>
Tue, 8 May 2018 22:21:28 +0000 (22:21 +0000)
------------------------------------------------------------------------
r327540 | ctopper | 2018-03-14 10:57:19 -0700 (Wed, 14 Mar 2018) | 7 lines

[X86] Add back fast-isel code for handling i8 shifts.

I removed this in r316797 because the coverage report showed no coverage and I thought it should have been handled by the auto generated table. I now see that there is code that bypasses the table if the shift amount is out of bounds.

This adds back the code. We'll codegen out of bounds i8 shifts to effectively (amount & 0x1f). The 0x1f is a strange quirk of x86 that shift amounts are always masked to 5-bits(except 64-bits). So if the masked value is still out bounds the result will be 0.

Fixes PR36731.
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_60@331815 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FastISel.cpp
test/CodeGen/X86/fast-isel-shift.ll

index 80ce3c579fe0ba4f8dc7b88fa947737deac17620..dca6c592614c9c0f4fa5c0e8b015eac6fc96574a 100644 (file)
@@ -1789,9 +1789,16 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) {
 bool X86FastISel::X86SelectShift(const Instruction *I) {
   unsigned CReg = 0, OpReg = 0;
   const TargetRegisterClass *RC = nullptr;
-  assert(!I->getType()->isIntegerTy(8) &&
-         "i8 shifts should be handled by autogenerated table");
-  if (I->getType()->isIntegerTy(16)) {
+  if (I->getType()->isIntegerTy(8)) {
+    CReg = X86::CL;
+    RC = &X86::GR8RegClass;
+    switch (I->getOpcode()) {
+    case Instruction::LShr: OpReg = X86::SHR8rCL; break;
+    case Instruction::AShr: OpReg = X86::SAR8rCL; break;
+    case Instruction::Shl:  OpReg = X86::SHL8rCL; break;
+    default: return false;
+    }
+  } else if (I->getType()->isIntegerTy(16)) {
     CReg = X86::CX;
     RC = &X86::GR16RegClass;
     switch (I->getOpcode()) {
@@ -1836,10 +1843,10 @@ bool X86FastISel::X86SelectShift(const Instruction *I) {
 
   // The shift instruction uses X86::CL. If we defined a super-register
   // of X86::CL, emit a subreg KILL to precisely describe what we're doing here.
-  assert(CReg != X86::CL && "CReg should be a super register of CL");
-  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
-          TII.get(TargetOpcode::KILL), X86::CL)
-    .addReg(CReg, RegState::Kill);
+  if (CReg != X86::CL)
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+            TII.get(TargetOpcode::KILL), X86::CL)
+      .addReg(CReg, RegState::Kill);
 
   unsigned ResultReg = createResultReg(RC);
   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(OpReg), ResultReg)
index 5d416e18260c5e669ed6f9e88f961341c02356d7..e9f01035b53aade5292e0e3e98ac353cee83be45 100644 (file)
@@ -381,3 +381,15 @@ define i64 @ashr_imm4_i64(i64 %a) {
   %c = ashr i64 %a, 4
   ret i64 %c
 }
+
+; Make sure we don't crash on out of bounds i8 shifts.
+define i8 @PR36731(i8 %a) {
+; CHECK-LABEL: PR36731:
+; CHECK:       ## %bb.0:
+; CHECK-NEXT:    movb $255, %cl
+; CHECK-NEXT:    shlb %cl, %dil
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %b = shl i8 %a, -1
+  ret i8 %b
+}