summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp47
-rw-r--r--llvm/test/CodeGen/AArch64/atomic-ops-lse.ll72
2 files changed, 82 insertions, 37 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp b/llvm/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
index c0888badb23..a43077cb88e 100644
--- a/llvm/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
+++ b/llvm/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
@@ -68,6 +68,51 @@ static bool usesFrameIndex(const MachineInstr &MI) {
return false;
}
+// Instructions that lose their 'read' operation for a subesquent fence acquire
+// (DMB LD) once the zero register is used.
+//
+// WARNING: The aquire variants of the instructions are also affected, but they
+// are split out into `atomicBarrierDroppedOnZero()` to support annotations on
+// assembly.
+static bool atomicReadDroppedOnZero(unsigned Opcode) {
+ switch (Opcode) {
+ case AArch64::LDADDB: case AArch64::LDADDH:
+ case AArch64::LDADDW: case AArch64::LDADDX:
+ case AArch64::LDADDLB: case AArch64::LDADDLH:
+ case AArch64::LDADDLW: case AArch64::LDADDLX:
+ case AArch64::LDCLRB: case AArch64::LDCLRH:
+ case AArch64::LDCLRW: case AArch64::LDCLRX:
+ case AArch64::LDCLRLB: case AArch64::LDCLRLH:
+ case AArch64::LDCLRLW: case AArch64::LDCLRLX:
+ case AArch64::LDEORB: case AArch64::LDEORH:
+ case AArch64::LDEORW: case AArch64::LDEORX:
+ case AArch64::LDEORLB: case AArch64::LDEORLH:
+ case AArch64::LDEORLW: case AArch64::LDEORLX:
+ case AArch64::LDSETB: case AArch64::LDSETH:
+ case AArch64::LDSETW: case AArch64::LDSETX:
+ case AArch64::LDSETLB: case AArch64::LDSETLH:
+ case AArch64::LDSETLW: case AArch64::LDSETLX:
+ case AArch64::LDSMAXB: case AArch64::LDSMAXH:
+ case AArch64::LDSMAXW: case AArch64::LDSMAXX:
+ case AArch64::LDSMAXLB: case AArch64::LDSMAXLH:
+ case AArch64::LDSMAXLW: case AArch64::LDSMAXLX:
+ case AArch64::LDSMINB: case AArch64::LDSMINH:
+ case AArch64::LDSMINW: case AArch64::LDSMINX:
+ case AArch64::LDSMINLB: case AArch64::LDSMINLH:
+ case AArch64::LDSMINLW: case AArch64::LDSMINLX:
+ case AArch64::LDUMAXB: case AArch64::LDUMAXH:
+ case AArch64::LDUMAXW: case AArch64::LDUMAXX:
+ case AArch64::LDUMAXLB: case AArch64::LDUMAXLH:
+ case AArch64::LDUMAXLW: case AArch64::LDUMAXLX:
+ case AArch64::LDUMINB: case AArch64::LDUMINH:
+ case AArch64::LDUMINW: case AArch64::LDUMINX:
+ case AArch64::LDUMINLB: case AArch64::LDUMINLH:
+ case AArch64::LDUMINLW: case AArch64::LDUMINLX:
+ return true;
+ }
+ return false;
+}
+
void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
MachineBasicBlock &MBB) {
const MachineFunction &MF = *MBB.getParent();
@@ -88,7 +133,7 @@ void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
continue;
}
- if (atomicBarrierDroppedOnZero(MI.getOpcode())) {
+ if (atomicBarrierDroppedOnZero(MI.getOpcode()) || atomicReadDroppedOnZero(MI.getOpcode())) {
LLVM_DEBUG(dbgs() << " Ignoring, semantics change with xzr/wzr.\n");
continue;
}
diff --git a/llvm/test/CodeGen/AArch64/atomic-ops-lse.ll b/llvm/test/CodeGen/AArch64/atomic-ops-lse.ll
index 22f2c855353..bebb285df4a 100644
--- a/llvm/test/CodeGen/AArch64/atomic-ops-lse.ll
+++ b/llvm/test/CodeGen/AArch64/atomic-ops-lse.ll
@@ -1311,7 +1311,7 @@ define void @test_atomic_load_add_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stadd w0, [x[[ADDR]]]
+; CHECK: ldadd w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1323,7 +1323,7 @@ define void @test_atomic_load_add_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stadd x0, [x[[ADDR]]]
+; CHECK: ldadd x{{[0-9]}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1387,7 +1387,7 @@ define void @test_atomic_load_add_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: staddl w0, [x[[ADDR]]]
+; CHECK: ldaddl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1399,7 +1399,7 @@ define void @test_atomic_load_add_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: staddl x0, [x[[ADDR]]]
+; CHECK: ldaddl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1696,7 +1696,7 @@ define void @test_atomic_load_and_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stclr w[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldclr w{{[0-9]+}}, w[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1709,7 +1709,7 @@ define void @test_atomic_load_and_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stclr x[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldclr x{{[0-9]+}}, x[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1774,7 +1774,7 @@ define void @test_atomic_load_and_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stclrl w[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldclrl w{{[0-9]*}}, w[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -1787,7 +1787,7 @@ define void @test_atomic_load_and_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stclrl x[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldclrl x{{[0-9]*}}, x[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2306,7 +2306,7 @@ define void @test_atomic_load_max_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stsmax w0, [x[[ADDR]]]
+; CHECK: ldsmax w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2318,7 +2318,7 @@ define void @test_atomic_load_max_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stsmax x0, [x[[ADDR]]]
+; CHECK: ldsmax x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2382,7 +2382,7 @@ define void @test_atomic_load_max_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stsmaxl w0, [x[[ADDR]]]
+; CHECK: ldsmaxl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2394,7 +2394,7 @@ define void @test_atomic_load_max_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stsmaxl x0, [x[[ADDR]]]
+; CHECK: ldsmaxl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2686,7 +2686,7 @@ define void @test_atomic_load_min_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stsmin w0, [x[[ADDR]]]
+; CHECK: ldsmin w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2698,7 +2698,7 @@ define void @test_atomic_load_min_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stsmin x0, [x[[ADDR]]]
+; CHECK: ldsmin x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2762,7 +2762,7 @@ define void @test_atomic_load_min_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stsminl w0, [x[[ADDR]]]
+; CHECK: ldsminl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -2774,7 +2774,7 @@ define void @test_atomic_load_min_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stsminl x0, [x[[ADDR]]]
+; CHECK: ldsminl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -3066,7 +3066,7 @@ define void @test_atomic_load_or_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stset w0, [x[[ADDR]]]
+; CHECK: ldset w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -3078,7 +3078,7 @@ define void @test_atomic_load_or_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stset x0, [x[[ADDR]]]
+; CHECK: ldset x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -3142,7 +3142,7 @@ define void @test_atomic_load_or_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stsetl w0, [x[[ADDR]]]
+; CHECK: ldsetl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -3154,7 +3154,7 @@ define void @test_atomic_load_or_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stsetl x0, [x[[ADDR]]]
+; CHECK: ldsetl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -3467,7 +3467,7 @@ define void @test_atomic_load_sub_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stadd w[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldadd w{{[0-9]+}}, w[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
@@ -3481,7 +3481,7 @@ define void @test_atomic_load_sub_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stadd x[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldadd x{{[0-9]+}}, x[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
@@ -3551,7 +3551,7 @@ define void @test_atomic_load_sub_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: staddl w[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldaddl w{{[0-9]*}}, w[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
@@ -3565,7 +3565,7 @@ define void @test_atomic_load_sub_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: staddl x[[NEW:[0-9]+]], [x[[ADDR]]]
+; CHECK: ldaddl x{{[0-9]*}}, x[[NEW:[1-9][0-9]*]], [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
@@ -4256,7 +4256,7 @@ define void @test_atomic_load_umax_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stumax w0, [x[[ADDR]]]
+; CHECK: ldumax w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4268,7 +4268,7 @@ define void @test_atomic_load_umax_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stumax x0, [x[[ADDR]]]
+; CHECK: ldumax x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4332,7 +4332,7 @@ define void @test_atomic_load_umax_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stumaxl w0, [x[[ADDR]]]
+; CHECK: ldumaxl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4344,7 +4344,7 @@ define void @test_atomic_load_umax_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stumaxl x0, [x[[ADDR]]]
+; CHECK: ldumaxl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4636,7 +4636,7 @@ define void @test_atomic_load_umin_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stumin w0, [x[[ADDR]]]
+; CHECK: ldumin w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4648,7 +4648,7 @@ define void @test_atomic_load_umin_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stumin x0, [x[[ADDR]]]
+; CHECK: ldumin x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4712,7 +4712,7 @@ define void @test_atomic_load_umin_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: stuminl w0, [x[[ADDR]]]
+; CHECK: lduminl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -4724,7 +4724,7 @@ define void @test_atomic_load_umin_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: stuminl x0, [x[[ADDR]]]
+; CHECK: lduminl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -5016,7 +5016,7 @@ define void @test_atomic_load_xor_i32_noret_monotonic(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: steor w0, [x[[ADDR]]]
+; CHECK: ldeor w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -5028,7 +5028,7 @@ define void @test_atomic_load_xor_i64_noret_monotonic(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: steor x0, [x[[ADDR]]]
+; CHECK: ldeor x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -5092,7 +5092,7 @@ define void @test_atomic_load_xor_i32_noret_release(i32 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
-; CHECK: steorl w0, [x[[ADDR]]]
+; CHECK: ldeorl w{{[0-9]+}}, w{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
@@ -5104,7 +5104,7 @@ define void @test_atomic_load_xor_i64_noret_release(i64 %offset) nounwind {
; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
-; CHECK: steorl x0, [x[[ADDR]]]
+; CHECK: ldeorl x{{[0-9]+}}, x{{[1-9][0-9]*}}, [x[[ADDR]]]
; CHECK-NOT: dmb
ret void
}
OpenPOWER on IntegriCloud