[llvm] r321551 - [PowerPC] Fix for PR35688 - handle out-of-range values for r+r to r+i conversion

Nemanja Ivanovic via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 29 04:22:27 PST 2017


Author: nemanjai
Date: Fri Dec 29 04:22:27 2017
New Revision: 321551

URL: http://llvm.org/viewvc/llvm-project?rev=321551&view=rev
Log:
[PowerPC] Fix for PR35688 - handle out-of-range values for r+r to r+i conversion

Revision 320791 introduced a pass that transforms reg+reg instructions to
reg+imm if they're fed by "load immediate". However, it didn't
handle out-of-range shifts correctly as reported in PR35688.
This patch fixes that and therefore the PR.

Furthermore, there was undefined behaviour in the patch where the RHS of an
initialization expression was 32 bits and constant `1` was shifted left 32
bits. This was fixed by ensuring the RHS is 64 bits just like the LHS.

Differential Revision: https://reviews.llvm.org/D41369

Added:
    llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir
    llvm/trunk/test/CodeGen/PowerPC/pr35688.ll
Modified:
    llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
    llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
    llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp
    llvm/trunk/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
    llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir

Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp?rev=321551&r1=321550&r2=321551&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp Fri Dec 29 04:22:27 2017
@@ -2433,7 +2433,7 @@ bool PPCInstrInfo::convertToImmediateFor
     int64_t MB = MI.getOperand(3).getImm();
     APInt InVal(Opc == PPC::RLDICL ? 64 : 32, SExtImm, true);
     InVal = InVal.rotl(SH);
-    uint64_t Mask = (1LU << (63 - MB + 1)) - 1;
+    uint64_t Mask = (1LLU << (63 - MB + 1)) - 1;
     InVal &= Mask;
     // Can't replace negative values with an LI as that will sign-extend
     // and not clear the left bits. If we're setting the CR bit, we will use
@@ -2457,8 +2457,8 @@ bool PPCInstrInfo::convertToImmediateFor
     int64_t ME = MI.getOperand(4).getImm();
     APInt InVal(32, SExtImm, true);
     InVal = InVal.rotl(SH);
-    // Set the bits (       MB + 32      ) to (       ME + 32      ).
-    uint64_t Mask = ((1 << (32 - MB)) - 1) & ~((1 << (31 - ME)) - 1);
+    // Set the bits (        MB + 32       ) to (        ME + 32       ).
+    uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1);
     InVal &= Mask;
     // Can't replace negative values with an LI as that will sign-extend
     // and not clear the left bits. If we're setting the CR bit, we will use
@@ -2527,6 +2527,7 @@ bool PPCInstrInfo::instrHasImmForm(const
   III.ConstantOpNo = 2;
   III.ImmWidth = 16;
   III.ImmMustBeMultipleOf = 1;
+  III.TruncateImmTo = 0;
   switch (Opc) {
   default: return false;
   case PPC::ADD4:
@@ -2600,10 +2601,6 @@ bool PPCInstrInfo::instrHasImmForm(const
   case PPC::RLWNM8:
   case PPC::RLWNMo:
   case PPC::RLWNM8o:
-  case PPC::RLDCL:
-  case PPC::RLDCLo:
-  case PPC::RLDCR:
-  case PPC::RLDCRo:
   case PPC::SLW:
   case PPC::SLW8:
   case PPC::SLWo:
@@ -2614,29 +2611,26 @@ bool PPCInstrInfo::instrHasImmForm(const
   case PPC::SRW8o:
   case PPC::SRAW:
   case PPC::SRAWo:
-  case PPC::SLD:
-  case PPC::SLDo:
-  case PPC::SRD:
-  case PPC::SRDo:
-  case PPC::SRAD:
-  case PPC::SRADo:
     III.SignedImm = false;
     III.ZeroIsSpecialOrig = 0;
     III.ZeroIsSpecialNew = 0;
     III.IsCommutative = false;
     // This isn't actually true, but the instructions ignore any of the
     // upper bits, so any immediate loaded with an LI is acceptable.
+    // This does not apply to shift right algebraic because a value
+    // out of range will produce a -1/0.
     III.ImmWidth = 16;
+    if (Opc == PPC::RLWNM || Opc == PPC::RLWNM8 ||
+        Opc == PPC::RLWNMo || Opc == PPC::RLWNM8o)
+      III.TruncateImmTo = 5;
+    else
+      III.TruncateImmTo = 6;
     switch(Opc) {
     default: llvm_unreachable("Unknown opcode");
     case PPC::RLWNM: III.ImmOpcode = PPC::RLWINM; break;
     case PPC::RLWNM8: III.ImmOpcode = PPC::RLWINM8; break;
     case PPC::RLWNMo: III.ImmOpcode = PPC::RLWINMo; break;
     case PPC::RLWNM8o: III.ImmOpcode = PPC::RLWINM8o; break;
-    case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break;
-    case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break;
-    case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break;
-    case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break;
     case PPC::SLW: III.ImmOpcode = PPC::RLWINM; break;
     case PPC::SLW8: III.ImmOpcode = PPC::RLWINM8; break;
     case PPC::SLWo: III.ImmOpcode = PPC::RLWINMo; break;
@@ -2645,14 +2639,62 @@ bool PPCInstrInfo::instrHasImmForm(const
     case PPC::SRW8: III.ImmOpcode = PPC::RLWINM8; break;
     case PPC::SRWo: III.ImmOpcode = PPC::RLWINMo; break;
     case PPC::SRW8o: III.ImmOpcode = PPC::RLWINM8o; break;
-    case PPC::SRAW: III.ImmOpcode = PPC::SRAWI; break;
-    case PPC::SRAWo: III.ImmOpcode = PPC::SRAWIo; break;
+    case PPC::SRAW:
+      III.ImmWidth = 5;
+      III.TruncateImmTo = 0;
+      III.ImmOpcode = PPC::SRAWI;
+      break;
+    case PPC::SRAWo:
+      III.ImmWidth = 5;
+      III.TruncateImmTo = 0;
+      III.ImmOpcode = PPC::SRAWIo;
+      break;
+    }
+    break;
+  case PPC::RLDCL:
+  case PPC::RLDCLo:
+  case PPC::RLDCR:
+  case PPC::RLDCRo:
+  case PPC::SLD:
+  case PPC::SLDo:
+  case PPC::SRD:
+  case PPC::SRDo:
+  case PPC::SRAD:
+  case PPC::SRADo:
+    III.SignedImm = false;
+    III.ZeroIsSpecialOrig = 0;
+    III.ZeroIsSpecialNew = 0;
+    III.IsCommutative = false;
+    // This isn't actually true, but the instructions ignore any of the
+    // upper bits, so any immediate loaded with an LI is acceptable.
+    // This does not apply to shift right algebraic because a value
+    // out of range will produce a -1/0.
+    III.ImmWidth = 16;
+    if (Opc == PPC::RLDCL || Opc == PPC::RLDCLo ||
+        Opc == PPC::RLDCR || Opc == PPC::RLDCRo)
+      III.TruncateImmTo = 6;
+    else
+      III.TruncateImmTo = 7;
+    switch(Opc) {
+    default: llvm_unreachable("Unknown opcode");
+    case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break;
+    case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break;
+    case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break;
+    case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break;
     case PPC::SLD: III.ImmOpcode = PPC::RLDICR; break;
     case PPC::SLDo: III.ImmOpcode = PPC::RLDICRo; break;
     case PPC::SRD: III.ImmOpcode = PPC::RLDICL; break;
     case PPC::SRDo: III.ImmOpcode = PPC::RLDICLo; break;
-    case PPC::SRAD: III.ImmOpcode = PPC::SRADI; break;
-    case PPC::SRADo: III.ImmOpcode = PPC::SRADIo; break;
+    case PPC::SRAD:
+      III.ImmWidth = 6;
+      III.TruncateImmTo = 0;
+      III.ImmOpcode = PPC::SRADI;
+       break;
+    case PPC::SRADo:
+      III.ImmWidth = 6;
+      III.TruncateImmTo = 0;
+      III.ImmOpcode = PPC::SRADIo;
+      break;
     }
     break;
   // Loads and stores:
@@ -2866,6 +2908,8 @@ bool PPCInstrInfo::transformToImmForm(Ma
     return false;
   if (Imm % III.ImmMustBeMultipleOf)
     return false;
+  if (III.TruncateImmTo)
+    Imm &= ((1 << III.TruncateImmTo) - 1);
   if (III.SignedImm) {
     APInt ActualValue(64, Imm, true);
     if (!ActualValue.isSignedIntN(III.ImmWidth))

Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h?rev=321551&r1=321550&r2=321551&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h Fri Dec 29 04:22:27 2017
@@ -97,6 +97,8 @@ struct ImmInstrInfo {
   uint64_t ImmOpcode : 16;
   // The size of the immediate.
   uint64_t ImmWidth : 5;
+  // The immediate should be truncated to N bits.
+  uint64_t TruncateImmTo : 5;
 };
 
 // Information required to convert an instruction to just a materialized

Modified: llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp?rev=321551&r1=321550&r2=321551&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp Fri Dec 29 04:22:27 2017
@@ -55,7 +55,7 @@ FixedPointRegToImm("ppc-reg-to-imm-fixed
                             "convert reg-reg instructions to reg-imm"));
 
 static cl::opt<bool>
-ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(false),
+ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(true),
               cl::desc("Convert eligible reg+reg instructions to reg+imm"));
 
 static cl::opt<bool>

Modified: llvm/trunk/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCPreEmitPeephole.cpp?rev=321551&r1=321550&r2=321551&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCPreEmitPeephole.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCPreEmitPeephole.cpp Fri Dec 29 04:22:27 2017
@@ -35,7 +35,7 @@ STATISTIC(NumRemovedInPreEmit,
           "Number of instructions deleted in pre-emit peephole");
 
 static cl::opt<bool>
-RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(false),
+RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true),
                    cl::desc("Run pre-emit peephole optimizations."));
 
 namespace {

Added: llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir?rev=321551&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir (added)
+++ llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir Fri Dec 29 04:22:27 2017
@@ -0,0 +1,1329 @@
+# RUN: llc -run-pass ppc-mi-peepholes -ppc-convert-rr-to-ri %s -o - | FileCheck %s
+# RUN: llc -start-after ppc-mi-peepholes -ppc-late-peephole %s -o - | FileCheck %s --check-prefix=CHECK-LATE
+
+--- |
+  ; ModuleID = 'convert-rr-to-ri-instrs.ll'
+  source_filename = "convert-rr-to-ri-instrs.c"
+  target datalayout = "e-m:e-i64:64-n32:64"
+  target triple = "powerpc64le-unknown-linux-gnu"
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testRLWNM(i32 zeroext %a) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i32 %a, 4
+    %and = and i32 %shl, 4080
+    ret i32 %and
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLWNM8(i64 %a) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i64 %a, 4
+    %and = and i64 %shl, 4080
+    ret i64 %and
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testRLWNMo(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 {
+  entry:
+    %and = and i32 %a, 255
+    %tobool = icmp eq i32 %and, 0
+    %cond = select i1 %tobool, i32 %b, i32 %a
+    ret i32 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLWNM8o(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %a.tr = trunc i64 %a to i32
+    %0 = shl i32 %a.tr, 4
+    %conv = and i32 %0, 4080
+    %tobool = icmp eq i32 %conv, 0
+    %conv1 = zext i32 %conv to i64
+    %cond = select i1 %tobool, i64 %b, i64 %conv1
+    ret i64 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testSLW(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i32 %a, %b
+    ret i32 %shl
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testSLWo(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i32 %a, %b
+    %tobool = icmp eq i32 %shl, 0
+    %cond = select i1 %tobool, i32 %b, i32 %a
+    ret i32 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testSRW(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 {
+  entry:
+    %shr = lshr i32 %a, %b
+    ret i32 %shr
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testSRWo(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 {
+  entry:
+    %shr = lshr i32 %a, %b
+    %tobool = icmp eq i32 %shr, 0
+    %cond = select i1 %tobool, i32 %b, i32 %a
+    ret i32 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define signext i32 @testSRAW(i32 signext %a, i32 signext %b) local_unnamed_addr #0 {
+  entry:
+    %shr = ashr i32 %a, %b
+    ret i32 %shr
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define signext i32 @testSRAWo(i32 signext %a, i32 signext %b) local_unnamed_addr #0 {
+  entry:
+    %shr = ashr i32 %a, %b
+    %tobool = icmp eq i32 %shr, 0
+    %cond = select i1 %tobool, i32 %b, i32 %shr
+    ret i32 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLDCL(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %and = and i64 %b, 63
+    %shl = shl i64 %a, %and
+    %sub = sub nsw i64 64, %and
+    %shr = lshr i64 %a, %sub
+    %or = or i64 %shr, %shl
+    ret i64 %or
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLDCLo(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %and = and i64 %b, 63
+    %shl = shl i64 %a, %and
+    %sub = sub nsw i64 64, %and
+    %shr = lshr i64 %a, %sub
+    %or = or i64 %shr, %shl
+    %tobool = icmp eq i64 %or, 0
+    %cond = select i1 %tobool, i64 %and, i64 %a
+    ret i64 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLDCR(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %and = and i64 %b, 63
+    %shl = shl i64 %a, %and
+    %sub = sub nsw i64 64, %and
+    %shr = lshr i64 %a, %sub
+    %or = or i64 %shr, %shl
+    ret i64 %or
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testRLDCRo(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %and = and i64 %b, 63
+    %shl = shl i64 %a, %and
+    %sub = sub nsw i64 64, %and
+    %shr = lshr i64 %a, %sub
+    %or = or i64 %shr, %shl
+    %tobool = icmp eq i64 %or, 0
+    %cond = select i1 %tobool, i64 %and, i64 %a
+    ret i64 %cond
+  }
+  
+  define i64 @testSLD(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i64 %a, %b
+    ret i64 %shl
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testSLDo(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i64 %a, %b
+    %tobool = icmp eq i64 %shl, 0
+    %cond = select i1 %tobool, i64 %b, i64 %a
+    ret i64 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testSRD(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shr = lshr i64 %a, %b
+    ret i64 %shr
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testSRDo(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shr = lshr i64 %a, %b
+    %tobool = icmp eq i64 %shr, 0
+    %cond = select i1 %tobool, i64 %b, i64 %a
+    ret i64 %cond
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testSRAD(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shr = ashr i64 %a, %b
+    ret i64 %shr
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define i64 @testSRADo(i64 %a, i64 %b) local_unnamed_addr #0 {
+  entry:
+    %shr = ashr i64 %a, %b
+    %tobool = icmp eq i64 %shr, 0
+    %cond = select i1 %tobool, i64 %b, i64 %shr
+    ret i64 %cond
+  }
+  
+  attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pwr9" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+power9-vector,+vsx,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" }
+  
+  !llvm.module.flags = !{!0, !1}
+  !llvm.ident = !{!2}
+  
+  !0 = !{i32 1, !"wchar_size", i32 4}
+  !1 = !{i32 7, !"PIC Level", i32 2}
+  !2 = !{!"clang version 6.0.0 (trunk 316067)"}
+  !3 = !{!4, !4, i64 0}
+  !4 = !{!"omnipotent char", !5, i64 0}
+  !5 = !{!"Simple C/C++ TBAA"}
+  !6 = !{!7, !7, i64 0}
+  !7 = !{!"short", !4, i64 0}
+  !8 = !{!9, !9, i64 0}
+  !9 = !{!"int", !4, i64 0}
+  !10 = !{!11, !11, i64 0}
+  !11 = !{!"long long", !4, i64 0}
+  !12 = !{!13, !13, i64 0}
+  !13 = !{!"double", !4, i64 0}
+  !14 = !{!15, !15, i64 0}
+  !15 = !{!"float", !4, i64 0}
+
+...
+---
+name:            testRLWNM
+# CHECK-ALL: name: testRLWNM
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: gprc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3
+  
+    %0 = COPY %x3
+    %1 = COPY %0.sub_32
+    %3 = IMPLICIT_DEF
+    %2 = LI 170
+    %4 = RLWNM killed %1, %2, 20, 27
+    ; CHECK: RLWINM killed %1, 10, 20, 27
+    ; CHECK-LATE: rlwinm 3, 3, 10, 20, 27
+    %x3 = EXTSW_32_64 %4
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLWNM8
+# CHECK-ALL: name: testRLWNM8
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3
+  
+    %0 = LI8 234
+    %1 = COPY %x3
+    %2 = RLWNM8 %1, %0, 20, 27
+    ; CHECK: RLWINM8 %1, 10, 20, 27
+    ; CHECK-LATE: rlwinm 3, 3, 10, 20, 27
+    %x3 = COPY %2
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLWNMo
+# CHECK-ALL: name: testRLWNMo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 3, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: gprc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+  - { id: 8, class: g8rc, preferred-register: '' }
+  - { id: 9, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = COPY %1.sub_32
+    %3 = LI -22
+    %4 = RLWNMo %2, %3, 24, 31, implicit-def %cr0
+    ; CHECK: RLWINMo %2, 10, 24, 31, implicit-def %cr0
+    ; CHECK-LATE: li 3, -22
+    ; CHECK-LATE: rlwinm. 5, 4, 10, 24, 31
+    %5 = COPY killed %cr0
+    %6 = ISEL %2, %3, %5.sub_eq
+    %8 = IMPLICIT_DEF
+    %7 = INSERT_SUBREG %8, killed %6, 1
+    %9 = RLDICL killed %7, 0, 32
+    %x3 = COPY %9
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLWNM8o
+# CHECK-ALL: name: testRLWNM8o
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 2, class: g8rc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+  - { id: 5, class: g8rc, preferred-register: '' }
+  - { id: 6, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 7, class: crrc, preferred-register: '' }
+  - { id: 8, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI8 -18
+    %3 = RLWNM8o %1, %2, 20, 27, implicit-def %cr0
+    ; CHECK: RLWINM8o %1, 14, 20, 27, implicit-def %cr0
+    ; CHECK-LATE: rlwinm. 3, 4, 14, 20, 27
+    %7 = COPY killed %cr0
+    %6 = RLDICL killed %3, 0, 32
+    %8 = ISEL8 %1, %6, %7.sub_eq
+    %x3 = COPY %8
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSLW
+# CHECK-ALL: name: testSLW
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+  - { id: 5, class: gprc, preferred-register: '' }
+  - { id: 6, class: g8rc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+  - { id: 8, class: gprc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = COPY %1.sub_32
+    %5 = LI 210
+    %8 = SLW killed %2, killed %5
+    ; CHECK: RLWINM killed %2, 18, 0, 13
+    ; CHECK-LATE: slwi 3, 4, 18
+    %x3 = EXTSW_32_64 %8
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSLWo
+# CHECK-ALL: name: testSLWo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 3, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: gprc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+  - { id: 8, class: g8rc, preferred-register: '' }
+  - { id: 9, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 35
+    %3 = COPY %0.sub_32
+    %4 = SLWo %3, %2, implicit-def %cr0
+    ; CHECK: ANDIo %3, 0, implicit-def %cr0
+    ; CHECK-LATE: andi. 5, 3, 0
+    %5 = COPY killed %cr0
+    %6 = ISEL %2, %3, %5.sub_eq
+    %8 = IMPLICIT_DEF
+    %7 = INSERT_SUBREG %8, killed %6, 1
+    %9 = RLDICL killed %7, 0, 32
+    %x3 = COPY %9
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRW
+# CHECK-ALL: name: testSRW
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+  - { id: 5, class: gprc, preferred-register: '' }
+  - { id: 6, class: g8rc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+  - { id: 8, class: gprc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 48
+    %5 = COPY %0.sub_32
+    %8 = SRW killed %5, killed %2
+    ; CHECK: LI 0
+    ; CHECK-LATE: li 3, 0
+    %x3 = EXTSW_32_64 %8
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRWo
+# CHECK-ALL: name: testSRWo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 3, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: gprc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+  - { id: 8, class: g8rc, preferred-register: '' }
+  - { id: 9, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI -7
+    %3 = COPY %0.sub_32
+    %4 = SRWo %3, %2, implicit-def %cr0
+    ; CHECK: ANDIo %3, 0, implicit-def %cr0
+    ; CHECK-LATE: andi. 5, 3, 0
+    %5 = COPY killed %cr0
+    %6 = ISEL %2, %3, %5.sub_eq
+    %8 = IMPLICIT_DEF
+    %7 = INSERT_SUBREG %8, killed %6, 1
+    %9 = RLDICL killed %7, 0, 32
+    %x3 = COPY %9
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRAW
+# CHECK-ALL: name: testSRAW
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+  - { id: 5, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 48
+    %3 = COPY %0.sub_32
+    %4 = SRAW killed %3, killed %2, implicit-def dead %carry
+    ; CHECK: LI 48
+    ; CHECK: SRAW killed %3, killed %2, implicit-def dead %carry
+    ; CHECK-LATE: sraw 3, 3, 4
+    %5 = EXTSW_32_64 killed %4
+    %x3 = COPY %5
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRAWo
+# CHECK-ALL: name: testSRAWo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: gprc_and_gprc_nor0, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: gprc, preferred-register: '' }
+  - { id: 7, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 80
+    %3 = COPY %0.sub_32
+    %4 = SRAWo killed %3, %2, implicit-def dead %carry, implicit-def %cr0
+    ; CHECK: SRAWo killed %3, %2, implicit-def dead %carry, implicit-def %cr0
+    ; CHECK-LATE: sraw. 3, 3, 4
+    %5 = COPY killed %cr0
+    %6 = ISEL %2, %4, %5.sub_eq
+    %7 = EXTSW_32_64 killed %6
+    %x3 = COPY %7
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLDCL
+# CHECK-ALL: name: testRLDCL
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = COPY %1.sub_32
+    %3 = LI 140
+    %4 = RLDCL %0, killed %3, 0
+    ; CHECK: RLDICL %0, 12, 0
+    ; CHECK-LATE: rotldi 3, 3, 12
+    %x3 = COPY %4
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLDCLo
+# CHECK-ALL: name: testRLDCLo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = RLDICL %1, 0, 58
+    %3 = LI -37
+    %4 = RLDCLo %0, killed %3, 0, implicit-def %cr0
+    ; CHECK: RLDICLo %0, 27, 0, implicit-def %cr0
+    ; CHECK-LATE: rldicl. 5, 3, 27, 0
+    %5 = COPY killed %cr0
+    %6 = ISEL8 %2, %0, %5.sub_eq
+    %x3 = COPY %6
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLDCR
+# CHECK-ALL: name: testRLDCR
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = COPY %1.sub_32
+    %3 = LI 300
+    %4 = RLDCR %0, killed %3, 0
+    ; CHECK: RLDICR %0, 44, 0
+    ; CHECK-LATE: rldicr 3, 3, 44, 0
+    %x3 = COPY %4
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLDCRo
+# CHECK-ALL: name: testRLDCRo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 3, class: gprc, preferred-register: '' }
+  - { id: 4, class: g8rc, preferred-register: '' }
+  - { id: 5, class: crrc, preferred-register: '' }
+  - { id: 6, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = RLDICL %1, 0, 58
+    %3 = LI -18
+    %4 = RLDCRo %0, killed %3, 0, implicit-def %cr0
+    ; CHECK: RLDICRo %0, 46, 0, implicit-def %cr0
+    ; CHECK-LATE: rldicr. 5, 3, 46, 0
+    %5 = COPY killed %cr0
+    %6 = ISEL8 %2, %0, %5.sub_eq
+    %x3 = COPY %6
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSLD
+# CHECK-ALL: name: testSLD
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI -13
+    %3 = SLD %0, killed %2
+    ; CHECK: LI8 0
+    ; CHECK-LATE: li 3, 0
+    %x3 = COPY %3
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSLDo
+# CHECK-ALL: name: testSLDo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 1, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: crrc, preferred-register: '' }
+  - { id: 5, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 88
+    %3 = SLDo %0, killed %2, implicit-def %cr0
+    ; CHECK: ANDIo8 %0, 0, implicit-def %cr0
+    ; CHECK-LATE: andi. 5, 3, 0
+    %4 = COPY killed %cr0
+    %5 = ISEL8 %1, %0, %4.sub_eq
+    %x3 = COPY %5
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRD
+# CHECK-ALL: name: testSRD
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 400
+    %3 = SRD %0, killed %2
+    ; CHECK: RLDICL %0, 48, 16
+    ; CHECK-LATE: rldicl 3, 3, 48, 16
+    %x3 = COPY %3
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRDo
+# CHECK-ALL: name: testSRDo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 1, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: crrc, preferred-register: '' }
+  - { id: 5, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 64
+    %3 = SRDo %0, killed %2, implicit-def %cr0
+    ; CHECK: ANDIo8 %0, 0, implicit-def %cr0
+    ; CHECK-LATE: andi. 5, 3, 0
+    %4 = COPY killed %cr0
+    %5 = ISEL8 %1, %0, %4.sub_eq
+    %x3 = COPY %5
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRAD
+# CHECK-ALL: name: testSRAD
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI -44
+    %3 = SRAD %0, killed %2, implicit-def dead %carry
+    ; CHECK: SRAD %0, killed %2, implicit-def dead %carry
+    ; CHECK-LATE: srad 3, 3, 4
+    %x3 = COPY %3
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testSRADo
+# CHECK-ALL: name: testSRADo
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc_and_g8rc_nox0, preferred-register: '' }
+  - { id: 4, class: crrc, preferred-register: '' }
+  - { id: 5, class: g8rc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+  - { reg: '%x4', virtual-reg: '%1' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3, %x4
+  
+    %1 = COPY %x4
+    %0 = COPY %x3
+    %2 = LI 68
+    %3 = SRADo %0, killed %2, implicit-def dead %carry, implicit-def %cr0
+    ; CHECK: SRADo %0, killed %2, implicit-def dead %carry, implicit-def %cr0
+    ; CHECK-LATE: srad. 3, 3, 5
+    %4 = COPY killed %cr0
+    %5 = ISEL8 %1, %3, %4.sub_eq
+    %x3 = COPY %5
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---

Modified: llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir?rev=321551&r1=321550&r2=321551&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir (original)
+++ llvm/trunk/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir Fri Dec 29 04:22:27 2017
@@ -569,6 +569,22 @@
   }
   
   ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testRLWINMFullReg(i32 zeroext %a) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i32 %a, 4
+    %and = and i32 %shl, 4080
+    ret i32 %and
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
+  define zeroext i32 @testRLWINMFullRegOutOfRange(i32 zeroext %a) local_unnamed_addr #0 {
+  entry:
+    %shl = shl i32 %a, 4
+    %and = and i32 %shl, 4080
+    ret i32 %and
+  }
+  
+  ; Function Attrs: norecurse nounwind readnone
   define i64 @testRLWINM8(i64 %a) local_unnamed_addr #0 {
   entry:
     %shl = shl i64 %a, 4
@@ -3938,6 +3954,110 @@ body:             |
     %x3 = EXTSW_32_64 %4
     BLR8 implicit %lr8, implicit %rm, implicit %x3
 
+...
+---
+name:            testRLWINMFullReg
+# CHECK-ALL: name: testRLWINMFullReg
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: gprc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3
+  
+    %0 = COPY %x3
+    %1 = COPY %0.sub_32
+    %3 = IMPLICIT_DEF
+    %2 = LI 2
+    %4 = RLWINM killed %2, 31, 0, 31
+    ; CHECK: LI 1
+    ; CHECK-LATE: li 3, 1
+    %x3 = EXTSW_32_64 %4
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
+...
+---
+name:            testRLWINMFullRegOutOfRange
+# CHECK-ALL: name: testRLWINMFullRegOutOfRange
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: g8rc, preferred-register: '' }
+  - { id: 1, class: gprc, preferred-register: '' }
+  - { id: 2, class: gprc, preferred-register: '' }
+  - { id: 3, class: g8rc, preferred-register: '' }
+  - { id: 4, class: gprc, preferred-register: '' }
+liveins:         
+  - { reg: '%x3', virtual-reg: '%0' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      
+stack:           
+constants:       
+body:             |
+  bb.0.entry:
+    liveins: %x3
+  
+    %0 = COPY %x3
+    %1 = COPY %0.sub_32
+    %3 = IMPLICIT_DEF
+    %2 = LI 1
+    %4 = RLWINM killed %2, 31, 0, 31
+    ; CHECK: RLWINM killed %2, 31, 0, 31
+    ; CHECK-LATE: rotlwi 3, 3, 31
+    %x3 = EXTSW_32_64 %4
+    BLR8 implicit %lr8, implicit %rm, implicit %x3
+
 ...
 ---
 name:            testRLWINM8

Added: llvm/trunk/test/CodeGen/PowerPC/pr35688.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/pr35688.ll?rev=321551&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/pr35688.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/pr35688.ll Fri Dec 29 04:22:27 2017
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown < %s  | \
+; RUN:   FileCheck %s
+; Function Attrs: nounwind
+define void @ec_GFp_nistp256_points_mul() {
+; CHECK-LABEL: ec_GFp_nistp256_points_mul:
+; CHECK:    ld 5, 0(3)
+; CHECK:    li 3, 127
+; CHECK:    li 4, 0
+; CHECK:    subfic 6, 5, 0
+; CHECK:    subfze 6, 4
+; CHECK:    sradi 7, 6, 63
+; CHECK:    srad 6, 6, 3
+; CHECK:    subfc 5, 5, 7
+; CHECK:    subfe 5, 4, 6
+; CHECK:    sradi 5, 5, 63
+entry:
+  br label %fe_cmovznz.exit.i534.i.15
+
+fe_cmovznz.exit.i534.i.15:                        ; preds = %fe_cmovznz.exit.i534.i.15, %entry
+  %0 = load i64, i64* undef, align 8
+  %1 = load i64, i64* undef, align 8
+  %conv.i69.i.i = zext i64 %0 to i128
+  %sub.i72.i.i = sub nsw i128 0, %conv.i69.i.i
+  %conv.i63.i.i = zext i64 %1 to i128
+  %add.neg.i.i.i = ashr i128 %sub.i72.i.i, 127
+  %sub.i65.i.i = sub nsw i128 %add.neg.i.i.i, %conv.i63.i.i
+  %sub.i65.lobit.i.i = ashr i128 %sub.i65.i.i, 127
+  %conv1.i58.i.i = and i128 %sub.i65.lobit.i.i, 18446744073709551615
+  %add3.i59.i.i = add nuw nsw i128 %conv1.i58.i.i, 0
+  %conv4.i60.i.i = trunc i128 %add3.i59.i.i to i64
+  store i64 %conv4.i60.i.i, i64* undef, align 16
+  br label %fe_cmovznz.exit.i534.i.15
+}




More information about the llvm-commits mailing list