[llvm] 53ae95c - [AMDGPU][GlobalISel] Combine shift + logic + shift with constant operands
Mirko Brkusanin via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 10 02:37:11 PST 2020
Author: Mirko Brkusanin
Date: 2020-11-10T11:32:13+01:00
New Revision: 53ae95c946c0d3a32e402d0815cf2de6c0f8c3d8
URL: https://github.com/llvm/llvm-project/commit/53ae95c946c0d3a32e402d0815cf2de6c0f8c3d8
DIFF: https://github.com/llvm/llvm-project/commit/53ae95c946c0d3a32e402d0815cf2de6c0f8c3d8.diff
LOG: [AMDGPU][GlobalISel] Combine shift + logic + shift with constant operands
This sequence of instructions can be simplified if they are single use and
some operands are constants. Additional combines may be applied afterwards.
Differential Revision: https://reviews.llvm.org/D90223
Added:
llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic-shlsat.mir
llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic.ll
Modified:
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 2fdae16f3cba..a807f7c0a8bc 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -59,6 +59,13 @@ struct RegisterImmPair {
int64_t Imm;
};
+struct ShiftOfShiftedLogic {
+ MachineInstr *Logic;
+ MachineInstr *Shift2;
+ Register LogicNonShiftReg;
+ uint64_t ValSum;
+};
+
using OperandBuildSteps =
SmallVector<std::function<void(MachineInstrBuilder &)>, 4>;
struct InstructionBuildSteps {
@@ -232,6 +239,14 @@ class CombinerHelper {
bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo);
bool applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo);
+ /// If we have a shift-by-constant of a bitwise logic op that itself has a
+ /// shift-by-constant operand with identical opcode, we may be able to convert
+ /// that into 2 independent shifts followed by the logic op.
+ bool matchShiftOfShiftedLogic(MachineInstr &MI,
+ ShiftOfShiftedLogic &MatchInfo);
+ bool applyShiftOfShiftedLogic(MachineInstr &MI,
+ ShiftOfShiftedLogic &MatchInfo);
+
/// Transform a multiply by a power-of-2 value to a left shift.
bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal);
bool applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal);
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index c529b37375f1..a19b0059b51a 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -166,6 +166,15 @@ def shift_immed_chain : GICombineRule<
[{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]),
(apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>;
+// Transform shift (logic (shift X, C0), Y), C1
+// -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same
+def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">;
+def shift_of_shifted_logic_chain : GICombineRule<
+ (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo),
+ (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d,
+ [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]),
+ (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>;
+
def mul_to_shl_matchdata : GIDefMatchData<"unsigned">;
def mul_to_shl : GICombineRule<
(defs root:$d, mul_to_shl_matchdata:$matchinfo),
@@ -562,4 +571,4 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
unmerge_merge, fabs_fabs_fold, unmerge_cst, unmerge_dead_to_trunc,
unmerge_zext_to_zext, trunc_ext_fold, trunc_shl,
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
- shift_immed_chain]>;
+ shift_immed_chain, shift_of_shifted_logic_chain]>;
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 2d859b6802c2..83fbbed2138d 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1617,6 +1617,122 @@ bool CombinerHelper::applyShiftImmedChain(MachineInstr &MI,
return true;
}
+bool CombinerHelper::matchShiftOfShiftedLogic(MachineInstr &MI,
+ ShiftOfShiftedLogic &MatchInfo) {
+ // We're trying to match the following pattern with any of
+ // G_SHL/G_ASHR/G_LSHR/G_USHLSAT/G_SSHLSAT shift instructions in combination
+ // with any of G_AND/G_OR/G_XOR logic instructions.
+ // %t1 = SHIFT %X, G_CONSTANT C0
+ // %t2 = LOGIC %t1, %Y
+ // %root = SHIFT %t2, G_CONSTANT C1
+ // -->
+ // %t3 = SHIFT %X, G_CONSTANT (C0+C1)
+ // %t4 = SHIFT %Y, G_CONSTANT C1
+ // %root = LOGIC %t3, %t4
+ unsigned ShiftOpcode = MI.getOpcode();
+ assert((ShiftOpcode == TargetOpcode::G_SHL ||
+ ShiftOpcode == TargetOpcode::G_ASHR ||
+ ShiftOpcode == TargetOpcode::G_LSHR ||
+ ShiftOpcode == TargetOpcode::G_USHLSAT ||
+ ShiftOpcode == TargetOpcode::G_SSHLSAT) &&
+ "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
+
+ // Match a one-use bitwise logic op.
+ Register LogicDest = MI.getOperand(1).getReg();
+ if (!MRI.hasOneNonDBGUse(LogicDest))
+ return false;
+
+ MachineInstr *LogicMI = MRI.getUniqueVRegDef(LogicDest);
+ unsigned LogicOpcode = LogicMI->getOpcode();
+ if (LogicOpcode != TargetOpcode::G_AND && LogicOpcode != TargetOpcode::G_OR &&
+ LogicOpcode != TargetOpcode::G_XOR)
+ return false;
+
+ // Find a matching one-use shift by constant.
+ const Register C1 = MI.getOperand(2).getReg();
+ auto MaybeImmVal = getConstantVRegValWithLookThrough(C1, MRI);
+ if (!MaybeImmVal)
+ return false;
+
+ const uint64_t C1Val = MaybeImmVal->Value;
+
+ auto matchFirstShift = [&](const MachineInstr *MI, uint64_t &ShiftVal) {
+ // Shift should match previous one and should be a one-use.
+ if (MI->getOpcode() != ShiftOpcode ||
+ !MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
+ return false;
+
+ // Must be a constant.
+ auto MaybeImmVal =
+ getConstantVRegValWithLookThrough(MI->getOperand(2).getReg(), MRI);
+ if (!MaybeImmVal)
+ return false;
+
+ ShiftVal = MaybeImmVal->Value;
+ return true;
+ };
+
+ // Logic ops are commutative, so check each operand for a match.
+ Register LogicMIReg1 = LogicMI->getOperand(1).getReg();
+ MachineInstr *LogicMIOp1 = MRI.getUniqueVRegDef(LogicMIReg1);
+ Register LogicMIReg2 = LogicMI->getOperand(2).getReg();
+ MachineInstr *LogicMIOp2 = MRI.getUniqueVRegDef(LogicMIReg2);
+ uint64_t C0Val;
+
+ if (matchFirstShift(LogicMIOp1, C0Val)) {
+ MatchInfo.LogicNonShiftReg = LogicMIReg2;
+ MatchInfo.Shift2 = LogicMIOp1;
+ } else if (matchFirstShift(LogicMIOp2, C0Val)) {
+ MatchInfo.LogicNonShiftReg = LogicMIReg1;
+ MatchInfo.Shift2 = LogicMIOp2;
+ } else
+ return false;
+
+ MatchInfo.ValSum = C0Val + C1Val;
+
+ // The fold is not valid if the sum of the shift values exceeds bitwidth.
+ if (MatchInfo.ValSum >= MRI.getType(LogicDest).getScalarSizeInBits())
+ return false;
+
+ MatchInfo.Logic = LogicMI;
+ return true;
+}
+
+bool CombinerHelper::applyShiftOfShiftedLogic(MachineInstr &MI,
+ ShiftOfShiftedLogic &MatchInfo) {
+ unsigned Opcode = MI.getOpcode();
+ assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
+ Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_USHLSAT ||
+ Opcode == TargetOpcode::G_SSHLSAT) &&
+ "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
+
+ LLT ShlType = MRI.getType(MI.getOperand(2).getReg());
+ LLT DestType = MRI.getType(MI.getOperand(0).getReg());
+ Builder.setInstrAndDebugLoc(MI);
+
+ Register Const = Builder.buildConstant(ShlType, MatchInfo.ValSum).getReg(0);
+
+ Register Shift1Base = MatchInfo.Shift2->getOperand(1).getReg();
+ Register Shift1 =
+ Builder.buildInstr(Opcode, {DestType}, {Shift1Base, Const}).getReg(0);
+
+ Register Shift2Const = MI.getOperand(2).getReg();
+ Register Shift2 = Builder
+ .buildInstr(Opcode, {DestType},
+ {MatchInfo.LogicNonShiftReg, Shift2Const})
+ .getReg(0);
+
+ Register Dest = MI.getOperand(0).getReg();
+ Builder.buildInstr(MatchInfo.Logic->getOpcode(), {Dest}, {Shift1, Shift2});
+
+ // These were one use so it's safe to remove them.
+ MatchInfo.Shift2->eraseFromParent();
+ MatchInfo.Logic->eraseFromParent();
+
+ MI.eraseFromParent();
+ return true;
+}
+
bool CombinerHelper::matchCombineMulToShl(MachineInstr &MI,
unsigned &ShiftVal) {
assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic-shlsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic-shlsat.mir
new file mode 100644
index 000000000000..95b8d15c0029
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic-shlsat.mir
@@ -0,0 +1,405 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=amdgcn -run-pass=amdgpu-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: ushlsat_and_1
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_and_1
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1073741820
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C1]], [[C]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 2
+ %4:_(s32) = G_CONSTANT i32 1073741820
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %6:_(s32) = G_USHLSAT %5, %2(s32)
+ $sgpr0 = COPY %6(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_and_2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_and_2
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 536870880
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 5
+ %4:_(s32) = G_CONSTANT i32 536870880
+ %6:_(s32) = G_CONSTANT i32 3
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %7:_(s32) = G_USHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_and_3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_and_3
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 19
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 65536
+ %6:_(s32) = G_CONSTANT i32 16
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %7:_(s32) = G_USHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_or_1
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_or_1
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073741821
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C1]], [[C]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 2
+ %4:_(s32) = G_CONSTANT i32 -1073741821
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %6:_(s32) = G_USHLSAT %5, %2(s32)
+ $sgpr0 = COPY %6(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_or_2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_or_2
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -536870881
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 5
+ %4:_(s32) = G_CONSTANT i32 -536870881
+ %6:_(s32) = G_CONSTANT i32 3
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %7:_(s32) = G_USHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_or_3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_or_3
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 19
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 65536
+ %6:_(s32) = G_CONSTANT i32 16
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %7:_(s32) = G_USHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: ushlsat_xor
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: ushlsat_xor
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 43690
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[USHLSAT:%[0-9]+]]:_(s32) = G_USHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[USHLSAT1:%[0-9]+]]:_(s32) = G_USHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[USHLSAT]], [[USHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[XOR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 43690
+ %6:_(s32) = G_CONSTANT i32 5
+ %3:_(s32) = G_USHLSAT %0, %2(s32)
+ %5:_(s32) = G_XOR %3, %4
+ %7:_(s32) = G_USHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_and_1
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_and_1
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1073741820
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C1]], [[C]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 2
+ %4:_(s32) = G_CONSTANT i32 1073741820
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %6:_(s32) = G_SSHLSAT %5, %2(s32)
+ $sgpr0 = COPY %6(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_and_2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_and_2
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 536870880
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 5
+ %4:_(s32) = G_CONSTANT i32 536870880
+ %6:_(s32) = G_CONSTANT i32 3
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %7:_(s32) = G_SSHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_and_3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_and_3
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 19
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[AND]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 65536
+ %6:_(s32) = G_CONSTANT i32 16
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_AND %3, %4
+ %7:_(s32) = G_SSHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_or_1
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_or_1
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073741821
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C1]], [[C]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 2
+ %4:_(s32) = G_CONSTANT i32 -1073741821
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %6:_(s32) = G_SSHLSAT %5, %2(s32)
+ $sgpr0 = COPY %6(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_or_2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_or_2
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -536870881
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 5
+ %4:_(s32) = G_CONSTANT i32 -536870881
+ %6:_(s32) = G_CONSTANT i32 3
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %7:_(s32) = G_SSHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_or_3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_or_3
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 19
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[OR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 65536
+ %6:_(s32) = G_CONSTANT i32 16
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_OR %3, %4
+ %7:_(s32) = G_SSHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
+---
+name: sshlsat_xor
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0
+
+ ; CHECK-LABEL: name: sshlsat_xor
+ ; CHECK: liveins: $sgpr0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 43690
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+ ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK: [[SSHLSAT:%[0-9]+]]:_(s32) = G_SSHLSAT [[COPY]], [[C2]](s32)
+ ; CHECK: [[SSHLSAT1:%[0-9]+]]:_(s32) = G_SSHLSAT [[C]], [[C1]](s32)
+ ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[SSHLSAT]], [[SSHLSAT1]]
+ ; CHECK: $sgpr0 = COPY [[XOR]](s32)
+ ; CHECK: SI_RETURN_TO_EPILOG implicit $sgpr0
+ %0:_(s32) = COPY $sgpr0
+ %2:_(s32) = G_CONSTANT i32 3
+ %4:_(s32) = G_CONSTANT i32 43690
+ %6:_(s32) = G_CONSTANT i32 5
+ %3:_(s32) = G_SSHLSAT %0, %2(s32)
+ %5:_(s32) = G_XOR %3, %4
+ %7:_(s32) = G_SSHLSAT %5, %6(s32)
+ $sgpr0 = COPY %7(s32)
+ SI_RETURN_TO_EPILOG implicit $sgpr0
+
+...
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic.ll
new file mode 100644
index 000000000000..0c7672123f0b
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-shift-of-shifted-logic.ll
@@ -0,0 +1,348 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %s | FileCheck %s
+
+define amdgpu_cs i32 @test_shl_and_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_and_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 4
+; CHECK-NEXT: s_and_b32 s0, s0, -16
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 2
+ %z2 = and i32 %z1, 1073741820
+ %z3 = shl i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_and_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_and_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 8
+; CHECK-NEXT: s_and_b32 s0, s0, 0xffffff00
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 5
+ %z2 = and i32 %z1, 536870880
+ %z3 = shl i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_and_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_and_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 5
+; CHECK-NEXT: s_and_b32 s0, s0, 0x7ffffff0
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 3
+ %z2 = and i32 %z1, 536870908
+ %z3 = shl i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_and_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_and_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 4
+; CHECK-NEXT: s_and_b32 s0, s0, 0xfffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 2
+ %z2 = and i32 %z1, 1073741820
+ %z3 = lshr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_and_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_and_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 8
+; CHECK-NEXT: s_and_b32 s0, s0, 0x3fffffc
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 5
+ %z2 = and i32 %z1, 536870880
+ %z3 = lshr i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_and_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_and_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 5
+; CHECK-NEXT: s_and_b32 s0, s0, 0x7ffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 3
+ %z2 = and i32 %z1, 536870908
+ %z3 = lshr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_and_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_and_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 4
+; CHECK-NEXT: s_and_b32 s0, s0, 0xfffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 2
+ %z2 = and i32 %z1, 1073741820
+ %z3 = ashr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_and_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_and_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 8
+; CHECK-NEXT: s_and_b32 s0, s0, 0x3fffffc
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 5
+ %z2 = and i32 %z1, 536870880
+ %z3 = ashr i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_and_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_and_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 5
+; CHECK-NEXT: s_and_b32 s0, s0, 0x7ffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 3
+ %z2 = and i32 %z1, 536870908
+ %z3 = ashr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_or_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_or_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 4
+; CHECK-NEXT: s_or_b32 s0, s0, 12
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 2
+ %z2 = or i32 %z1, 3221225475
+ %z3 = shl i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_or_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_or_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 8
+; CHECK-NEXT: s_or_b32 s0, s0, 0xfffffc00
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 3
+ %z2 = or i32 %z1, 536870880
+ %z3 = shl i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_or_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_or_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 5
+; CHECK-NEXT: s_or_b32 s0, s0, 0x7fffff80
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 2
+ %z2 = or i32 %z1, 268435440
+ %z3 = shl i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_or_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_or_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 4
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 2
+ %z2 = or i32 %z1, 3
+ %z3 = lshr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_or_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_or_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 8
+; CHECK-NEXT: s_or_b32 s0, s0, 0xffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 3
+ %z2 = or i32 %z1, 536870880
+ %z3 = lshr i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_or_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_or_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 5
+; CHECK-NEXT: s_or_b32 s0, s0, 0x1fffffe
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 2
+ %z2 = or i32 %z1, 268435440
+ %z3 = lshr i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_or_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_or_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 4
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 2
+ %z2 = or i32 %z1, 3
+ %z3 = ashr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_or_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_or_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 8
+; CHECK-NEXT: s_or_b32 s0, s0, 0xffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 3
+ %z2 = or i32 %z1, 536870880
+ %z3 = ashr i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_or_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_or_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 5
+; CHECK-NEXT: s_or_b32 s0, s0, 0x1fffffe
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 2
+ %z2 = or i32 %z1, 268435440
+ %z3 = ashr i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_xor_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_xor_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 4
+; CHECK-NEXT: s_xor_b32 s0, s0, -16
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 2
+ %z2 = xor i32 %z1, 1073741820
+ %z3 = shl i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_xor_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_xor_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 6
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 1
+ %z2 = xor i32 %z1, 4160749568
+ %z3 = shl i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_shl_xor_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_shl_xor_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshl_b32 s0, s0, 5
+; CHECK-NEXT: s_xor_b32 s0, s0, 56
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = shl i32 %arg1, 2
+ %z2 = xor i32 %z1, 3221225479
+ %z3 = shl i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_xor_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_xor_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 4
+; CHECK-NEXT: s_xor_b32 s0, s0, 0xfffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 2
+ %z2 = xor i32 %z1, 1073741820
+ %z3 = lshr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_xor_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_xor_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 6
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 1
+ %z2 = xor i32 %z1, 31
+ %z3 = lshr i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_lshr_xor_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_lshr_xor_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_lshr_b32 s0, s0, 5
+; CHECK-NEXT: s_xor_b32 s0, s0, 0x18000000
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = lshr i32 %arg1, 2
+ %z2 = xor i32 %z1, 3221225479
+ %z3 = lshr i32 %z2, 3
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_xor_1(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_xor_1:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 4
+; CHECK-NEXT: s_xor_b32 s0, s0, 0xfffffff
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 2
+ %z2 = xor i32 %z1, 1073741820
+ %z3 = ashr i32 %z2, 2
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_xor_2(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_xor_2:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 6
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 1
+ %z2 = xor i32 %z1, 31
+ %z3 = ashr i32 %z2, 5
+ ret i32 %z3
+}
+
+define amdgpu_cs i32 @test_ashr_xor_3(i32 inreg %arg1) {
+; CHECK-LABEL: test_ashr_xor_3:
+; CHECK: ; %bb.0: ; %.entry
+; CHECK-NEXT: s_ashr_i32 s0, s0, 5
+; CHECK-NEXT: s_xor_b32 s0, s0, 0xf8000000
+; CHECK-NEXT: ; return to shader part epilog
+.entry:
+ %z1 = ashr i32 %arg1, 2
+ %z2 = xor i32 %z1, 3221225479
+ %z3 = ashr i32 %z2, 3
+ ret i32 %z3
+}
More information about the llvm-commits
mailing list